2010-07-28 12 views
5

Próbowałem napisać małą bibliotekę za pomocą Thora, aby pomóc mi w szybkim tworzeniu nowych projektów i stron. Napisałem tę małą metodę:Net :: Polecenie SSH sudo zawiesza się po wprowadzeniu hasła

def ssh(cmd) 
    Net::SSH.start(server_ip, user, :port => port) do |session| 
    session.exec cmd 
    end 
end 

po prostu pomóc mi w uruchamianiu szybkich poleceń na zdalnych serwerach w razie potrzeby.

Problem polega na tym, że jeśli potrzebuję wykonać polecenie pod sudo na zdalnym końcu, skrypt wydaje mi się zawieszony. Na przykład podczas wykonywania tego ...

ssh("sudo cp #{file_from_path} #{file_to_path}") 

Skrypt zapyta mnie o hasło

[sudo] password for user: 

Ale wtedy cały hhangs rzeczą po wpisaniu go w.

Czy ktoś się z wiedzą dlaczego wisi dokładnie i co mogę zrobić, aby uruchomić polecenie sudo na zdalnym serwerze pod Net :: SSH (lub inną alternatywą)?

* uwaga: zanim zasugerowałem, początkowo zacząłem pisać tę bibliotekę jako przepis pod Capistrano, dopóki nie natknąłem się na Thora i pomyślałem, że to dobra okazja, aby go wypróbować. Nie jestem przeciwny konieczności przeniesienia całości z powrotem do Capistrano, jeśli to konieczne, ale byłbym naprawdę zaskoczony, gdyby nie było łatwego sposobu uruchamiania poleceń sudo na zdalnym serwerze.

+0

Czy możesz podać hasło? 'ssh (" sudo cp # {from} # {to} <"mysupass") ' – Fosco

+0

oczywiście zapomniałem uciec z podwójnych cytatów z poprzedniego komentarza – Fosco

+0

Próbowałem tego, ale to nie działa. "bash: mysupass: Brak takiego pliku lub katalogu." Czy jest to próba podania hasła do wiersza? Jeśli tak, pomysł może zadziałać, ale składnia prawdopodobnie jest właśnie wyłączona. Zobaczę, co mogę znaleźć – joeellis

Odpowiedz

1

Pierwszą rzeczą, którą warto wypróbować, jest użycie kluczy publicznych zamiast haseł do zalogowania się. Następnie spróbuj uruchomić polecenie z interaktywnej powłoki.

Na przykład:

(Ta część naprawdę zależy od oprogramowania klient/serwer masz)

$ ssh-keygen 
$ scp .ssh/id-dsa.pub server: 
$ ssh server 
server$ cat id-dsa.pub >> .ssh/authorizedkeys 

$ scp -c "ls" 

to powinno działać bez żadnej podpowiedzi, jeśli klucz podziału był udany.

+1

Właściwie używam kluczy publicznych, a hasło, o które prosił, nie jest hasłem do połączenia ssh, ale hasłem do uruchomienia polecenia sudo, więc przynajmniej wiem, że to się łączy, ale zawiesza się po tym, jak wypełniłem hasło sudo: – joeellis

+0

Możesz spróbować ustawić sudo, aby nie pytać o hasło dla konkretnego użytkownika – sukru

+0

Próbowałem tego w pliku sudoers na serwerze zdalnym, dodając następujące linie na końcu "użytkownik ALL = (ALL) ALL ", ale wciąż jestem podpowiadany jest niepoprawnie? – joeellis

4

Jest możliwe, aby ustawić go z net/ssh, ale to naprawdę zbyt wiele wysiłku, wystarczy wykonać polecenie ssh tak:

system("ssh", "-t", "#{user}@#{host}", "sudo cp #{file_from_path} #{file_to_path}") 

Ten -t oznacza przeznaczyć tty. Bez niego nadal będzie działać, ale twoje hasło będzie widoczne w sposób przejrzysty.

(Zakładam, że zamierzasz wpisać hasło sudo ręcznie, jeśli nie, przejdź w sposób autoryzowany klawiszami).

5

Oto możliwe rozwiązanie:

def ssh(cmd) 
    Net::SSH.start(server_ip, user, :port => port) do |session| 
    result = nil 
    session.exec!(cmd) do |channel, stream, data| 
     if data =~ /^\[sudo\] password for user:/ 
     channel.send_data 'your_sudo_password' 
     else 
     result << data 
     end 
    end 
    result # content of 'cmd' result 
    end 
end 

Ale z tego rozwiązania, masz hasła administratora napisane w jasny w pliku skryptu gdzieś ...

+0

@japancheese Ostatni napisany przez Ciebie kod nie obsługuje hasła do sudo. To dokładnie ten sam kod podany w pytaniu. – Riba

-1

Właściwie w końcu zrobiłem coś bardzo podobna do sugestii Riba (choć jego/jej kod jest znacznie lepsza i mądrzejsza, myślę)

def ssh(env, cmd, opts={}) 
    Net::SSH.start(config[env]["ip"], config[env]["user"], :port => config[env]["port"]) do |session| 
     cmd = "sudo #{cmd}" if opts[:sudo] 
     print cmd 
     session.exec cmd 
    end 
end 
13

mam nadzieję, że to pomoże ktoś szuka.Musiałem też sudo podczas wdrażania (ponownym cienkich instancji)

# deploy.rake 
require 'net/ssh' 

# INITIALIZE CONSTANTS HERE 
HOST = 'yourwebsite.com' 
USER = 'admin' 
PASSWORD = 'your server password' # or use ENV variables? 
# etc. 

namespace :deploy do 
    namespace :staging do 
    task :restart do 
     commands = [ 
     "cd #{PATH_TO_STAGING_APP} && git checkout master", 
     "git reset --hard HEAD", 
     "git pull origin master", 
     "bundle install --without test development", 
     "sudo thin restart -C /etc/thin/#{STAGING_APP}.yml" 
     ] 

     Net::SSH.start(HOST, USER, :password => PASSWORD) do |ssh| 
     ssh.open_channel do |channel| 
      channel.request_pty do |ch, success| 
      if success 
       puts "Successfully obtained pty" 
      else 
       puts "Could not obtain pty" 
      end 
      end 

      channel.exec(commands.join(';')) do |ch, success| 
      abort "Could not execute commands!" unless success 

      channel.on_data do |ch, data| 
       puts "#{data}" 
       channel.send_data "#{PASSWORD}\n" if data =~ /password/ 
      end 

      channel.on_extended_data do |ch, type, data| 
       puts "stderr: #{data}" 
      end 

      channel.on_close do |ch| 
       puts "Channel is closing!" 
      end 
      end 
     end 
     ssh.loop 
     end 
    end 
    end 
end 

Zauważ, że jeden kanał może wykonać tylko jedno polecenie. Stąd ja przykuty komendy wraz z commands.join(';')

referencyjny: Net::SSH::Connection::Channel

2

oszukiwałem wykonując dodawanie to:

sudouser ALL=(ALL:ALL) NOPASSWD: ALL 

do /etc/sudoers

Należy także pamiętać, aby używać visudo podczas edycji !! !

Powiązane problemy