Rispondere a una richiesta SSH prima del primo comando con rubino e Net :: SSH
Domanda
Sto cercando di connettersi, utilizzando Net :: SSH, a un server che subito dopo login esegue uno script che richiede l'input dall'utente. L'utente deve inserire "1" o "2" e riceveranno alcuni dati via nel terminale in seguito.
Il mio problema è che, anche se sono in grado di connettersi, non riesco a trovare un modo per inviare "1 \ n" al server e per ricevere l'uscita.
Il seguente codice si ferma a. "INFO - net.ssh.connection.session [80906b74]: channel_open_confirmation: 0 0 0 32768"
Utilizzo channel.exec ( "1 \ n") invece di channel.send_data sorprende non funziona neanche.
Net::SSH.start('host', 'user', :password => "pass", :auth_methods => ["password"], :verbose => :debug) do |session|
session.open_channel do |channel|
channel.on_data do |ch, data|
STDOUT.print data
end
channel.send_data( "1\n")
end
session.loop
end
Tutte le idee, chiunque?
Grazie in anticipo
Soluzione
Si può verificare che la chiamata send_data
sta accadendo dopo si ottiene il prompt dal server remoto? Prova la costruzione di un blocco channel.on_data
intorno alla vostra chiamata send_data
in modo che è possibile verificare che si ottiene il prompt atteso dal server prima di inviare una risposta.
Non si potrebbe desiderare di essere utilizzando exec
qui. Dalla documentazione per Net :: SSH :: Collegamento :: Canale:
invia una richiesta di canale chiedendo che il comando dato essere invocato.
si vogliono inviare una stringa di testo per rispondere ad un richiamo, non richiamare un comando. La documentazione mostrano exec
essere utilizzati per inviare comandi CLI completa come "ls -l / casa".
Invece, send_data
è probabilmente quello che volete. La documentazione mostrano utilizzato per inviare testo arbitrario come channel.send_data("the password\n")
. Si noti, tuttavia, questa frase nella documentazione:
Si noti che non invia immediatamente i dati attraverso il canale, ma limitandosi aggiunge i dati forniti al buffer di uscita del canale, preparatoria per essere confezionati e inviato la prossima volta che la connessione è accettare i dati.
Si potrebbe voler dare un'occhiata a channel.request_pty
. Sembra essere progettata per l'interazione con un'applicazione basata su console.
Se si sta tentando di (in sostanza) scritto una sessione SSH che normalmente fare manualmente, si può trovare più facile da usare un'interfaccia expect
-simili (per esempio, un gioiello come sshExpect potrebbe essere la pena di provare).
Altri suggerimenti
Grazie a tutti per i puntatori. Sono stato in grado di mettere il dito sul problema - oltre ad utilizzare channel.request_pty era anche necessario richiedere una conchiglia. Di seguito, infine, funziona come previsto:
Net::SSH.start('host', 'user', :password => "pass", :auth_methods => ["password"]) do |session|
session.open_channel do |channel|
channel.request_pty do |ch, success|
raise "Error requesting pty" unless success
ch.send_channel_request("shell") do |ch, success|
raise "Error opening shell" unless success
end
end
channel.on_data do |ch, data|
STDOUT.print data
end
channel.on_extended_data do |ch, type, data|
STDOUT.print "Error: #{data}\n"
end
channel.send_data( "1\n" )
session.loop
end
end
Io non sono terribilmente familiarità con le librerie Net :: SSH quindi non posso aiutare in questo per-sé, ma suona come si potrebbe ottenere ciò che si desidera utilizzare Capistrano .
Per esempio io ho un compito Capistrano che si collega a un server remoto, esegue un comando che si aspetta di ingresso e poi continua. Capistrano cura la I / O remoto. Forse questo potrebbe essere una soluzione per voi?
Speranza che aiuta!
Se eseguo "1\n"
in un guscio di risposta che ottiene è: bash: 1: command not found
Se eseguo echo "1"
ottengo: 1
Sei sicuro di voler provare ad eseguire il testo che si sta inviando? Forse stavi cercando qualcosa di simile:
output = ""
Net::SSH.start('host', 'user', :password => "pass") do |ssh|
output = ssh.exec! "echo 1"
end
puts output
Io non sono esperto con quello lib, ma su SSH è possibile aprire più canali. Forse il server risponde solo al primo canale predefinito e se si apre un altro si ottiene un guscio fresco.