2010-07-28 11 views
5

Ho cercato di scrivere una piccola libreria usando Thor per aiutarmi nella creazione rapida di nuovi progetti e siti. Ho scritto questo piccolo metodo:Net: Il comando sudo SSH si blocca dopo aver immesso la password

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

per assistermi solo nell'esecuzione di comandi rapidi su server remoti quando necessario.

Il problema è quando ho bisogno di eseguire un comando sudo sul lato remoto, lo script sembra appeso su di me. Per esempio quando si esegue questo ...

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

La sceneggiatura mi chiederà una password

[sudo] password for user: 

Ma poi il tutto hhangs dopo aver digitato in.

qualcuno dovrebbe accadere a sapere perché si blocca esattamente, e cosa posso fare per eseguire il comando sudo su un server remoto sotto Net :: SSH (o qualche alternativa)?

* Nota: Prima di suggerire, avevo inizialmente iniziato a scrivere questa libreria come una ricetta sotto Capistrano, fino a quando non incontrai Thor, e pensai che sarebbe stata una buona occasione per provarlo. Non sono contrario a dover riportare tutto a Capistrano se necessario, ma sarei davvero sorpreso se non c'è un modo semplice per eseguire i comandi sudo su un server remoto.

+0

Sei in grado di reindirizzare la password? 'ssh (" sudo cp # {da} # {a} <"mysupass") ' – Fosco

+0

ovviamente ho dimenticato di sfuggire alle virgolette nel commento precedente – Fosco

+0

Ho provato questo, ma non funziona. "bash: mysupass: nessun file o directory". Si tratta di un tentativo di reindirizzare la password al prompt? In tal caso, l'idea potrebbe funzionare, ma probabilmente la sintassi è appena terminata. Vedrò cosa riesco a trovare su – joeellis

risposta

1

La prima cosa che dovresti provare è usare le chiavi pubbliche invece delle password per accedere. Quindi prova anche a eseguire il comando dalla shell interattiva.

Ad esempio:

(Questa parte in realtà dipende il software del server/client avete)

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

$ scp -c "ls" 

questo dovrebbe funzionare senza alcuna richiesta, se la condivisione chiave era successo.

+1

Attualmente sto usando le chiavi pubbliche, la password che richiede non è la password per la connessione ssh, ma la password per sudo per eseguire il comando, quindi almeno so che si connette, ma si blocca dopo che ho compilato la password sudo – joeellis

+0

Si potrebbe provare a impostare sudo di non chiedere una password per l'utente specifico – sukru

+0

Ho provato questo nel file sudoers sul server remoto aggiungendo le righe follower alla fine "utente ALL = (TUTTI) TUTTI ", ma mi stanno ancora chiedendo è errato? – joeellis

4

E 'possibile configurarlo con net/ssh, ma è davvero troppo sforzo, basta eseguire ssh comando come questo:

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

Questo significa -t di destinare una tty. Senza di esso funzionerà ancora, ma la tua password sarà visibile in chiaro.

(presumo che si intenda digitare la password sudo manualmente. In caso contrario, utilizzare le chiavi autorizzate).

5

Ecco una possibile soluzione:

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 

Ma con questa soluzione, avete la vostra password di root writen in chiaro in un file di script da qualche parte ...

+0

@japancheese L'ultimo codice che hai pubblicato non gestisce la password del prompt sudo. È esattamente lo stesso codice fornito nella tua domanda. – Riba

-1

In realtà, alla fine, ho fatto qualcosa molto simile al suggerimento di Riba (anche se il suo/la sua codice è molto meglio e più intelligente, credo)

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

Spero che questo vi aiuterà qualcuno alla ricerca.Ho anche bisogno di sudo durante la distribuzione (il riavvio casi sottili)

# 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 

Si noti che un canale in grado di eseguire un solo comando. Quindi ho incatenato i comandi insieme commands.join(';')

Riferimento: Net::SSH::Connection::Channel

2

ho barato facendo l'aggiunta di questo:

sudouser ALL=(ALL:ALL) NOPASSWD: ALL 

a /etc/sudoers

Inoltre, assicurarsi di utilizzare visudo durante la modifica !! !

Problemi correlati