2010-07-28 14 views
5

Ich habe versucht, eine kleine Bibliothek mit Thor zu schreiben, um mir bei der Erstellung neuer Projekte und Websites zu helfen. Ich schrieb diese kleine Methode:Net :: SSH sudo Befehl hängt nach der Eingabe des Passwortes

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

unterstützen mich nur in laufender Schnell Befehle auf Remote-Servern bei Bedarf.

Das Problem ist, wenn ich einen Befehl unter sudo auf dem Remote-Ende ausführen muss, scheint das Skript nur auf mich zu hängen. Zum Beispiel bei der Ausführung dieses ...

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

Das Skript mich nach einem Passwort

[sudo] password for user: 

Aber dann die ganze Sache hhangs nach der Eingabe auffordern, wird es in.

jedem passieren würde wissen Warum hängt es genau, und was kann ich tun, um Sudo-Befehl auf einem Remote-Server unter Net :: SSH (oder eine Alternative) auszuführen?

* Hinweis: Bevor ich vorgeschlagen hatte, hatte ich ursprünglich begonnen, diese Bibliothek als Rezept unter Capistrano zu schreiben, bis ich auf Thor stieß, und dachte, es wäre eine gute Gelegenheit, es auszuprobieren. Ich bin nicht dagegen, wenn ich das ganze Ding nach Capistrano zurückschicken müsste, aber ich wäre wirklich überrascht, wenn es keine einfache Möglichkeit gäbe, sudo-Befehle auf einem entfernten Server auszuführen.

+0

Können Sie das Passwort eingeben? 'ssh (" sudo cp # {von} # {to} <"mysupass") ' – Fosco

+0

natürlich habe ich vergessen, die doppelten Anführungszeichen im vorherigen Kommentar zu entfernen. – Fosco

+0

Versucht dies, aber es funktioniert nicht. Es kommt wieder mit "bash: mysupass: Keine solche Datei oder kein Verzeichnis". Ist das ein Versuch, das Passwort an die Eingabeaufforderung weiterzuleiten? Wenn ja, könnte die Idee funktionieren, aber die Syntax ist wahrscheinlich einfach aus. Ich werde sehen, was ich finden kann dass. – joeellis

Antwort

1

Das erste, was Sie ausprobieren möchten, ist die Verwendung von öffentlichen Schlüsseln anstelle von Passwörtern für die Anmeldung. Versuchen Sie dann auch, den Befehl von der interaktiven Shell auszuführen.

Zum Beispiel:

(Dieser Teil hängt wirklich von der Server/Client-Software, die Sie haben)

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

$ scp -c "ls" 

dies ohne Aufforderungen funktionieren soll, wenn der Schlüssel-Sharing erfolgreich war.

+1

Eigentlich bin ich mit öffentlichen Schlüsseln. das Passwort für ist Aufforderung ist nicht das Passwort für die sSH-Verbindung, aber das Passwort für sudo, um den Befehl auszuführen. Also ich zumindest wissen, dass es eine Verbindung, aber es hängt, nachdem ich fülle das sudo Passwort. – joeellis

+0

Sie versuchen, sudo könnten Einstellung nicht für ein Kennwort für den jeweiligen Benutzer zu fragen. – sukru

+0

ich hatte Linien, indem die Folger dies in der sudoers-Datei auf dem Remote-Server versucht, am Ende „user ALL = (ALL) ALL ", aber ich werde immer noch aufgefordert. Mache ich th ist falsch? – joeellis

4

Es ist möglich, es mit net/ssh einzurichten, aber es ist wirklich zu viel Aufwand, nur ssh Befehl wie folgt ausführen:

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

Dieses -t bedeutet einen tty zuzuordnen. Ohne es wird es immer noch funktionieren, aber Ihr Passwort wird klar angezeigt.

(Ich nehme an, Sie beabsichtigen, sudo Passwort manuell einzugeben. Wenn nicht, gehen Sie die autorisierte Schlüssel Weg).

5

Hier eine mögliche Lösung ist:

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 

Aber mit dieser Lösung Sie Ihr Root-Passwort hat in klar in einer Skriptdatei irgendwo ...

+0

@japancheese Der letzte von Ihnen gepostete Code verarbeitet das sudo-Eingabeaufforderungskennwort nicht. Es ist genau der gleiche Code in Ihrer Frage. – Riba

-1

Eigentlich am Ende writen, habe ich etwas sehr ähnlich der Vorschlag von Riba (obwohl sein/ihr Code ist viel besser und klüger, ich denke)

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

ich diese Hoffnung sucht jemand helfen.Ich braucht auch sudo während des Einsatzes (Neustart dünne Instanzen)

# 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 

Beachten Sie, dass ein Kanal nur einen Befehl ausführen kann. Daher gekettet ich die Befehle zusammen mit commands.join(';')

Referenz: Net::SSH::Connection::Channel

2

ich betrogen, indem Sie diese Zugabe:

sudouser ALL=(ALL:ALL) NOPASSWD: ALL 

zu /etc/sudoers

auch sicher, dass visudo zu verwenden, wenn die Bearbeitung !! !