Répondre à une invite de SSH avant la première commande avec Ruby et Net :: SSH
Question
Je suis en train de se connecter, en utilisant Net :: SSH, à un serveur immédiatement après connexion exécute un script qui nécessite une intervention de l'utilisateur. L'utilisateur doit entrer « 1 » ou « 2 » et recevra des données par l'intermédiaire du terminal après.
Mon problème est que, même si je suis en mesure de se connecter, je ne peux pas trouver un moyen d'envoyer « 1 \ n » au serveur et pour recevoir la sortie.
Le code suivant arrête à. "INFO - net.ssh.connection.session [80906b74]: channel_open_confirmation: 0 0 0 32768"
Utilisation channel.exec ( "1 \ n") au lieu de channel.send_data ne fonctionne pas sans surprise non plus.
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
Toutes les idées, anyone?
Merci d'avance
La solution
Pouvez-vous vérifier que votre appel send_data
se passe après vous obtenez l'invite du serveur distant? Essayez la construction d'un bloc de channel.on_data
autour de votre appel send_data
afin que vous puissiez vérifier que vous obtenez l'invite attendue du serveur avant d'envoyer une réponse.
Vous voudrez peut-être pas être en utilisant exec
ici. De la documentation pour Net :: SSH :: Connexion :: Canal:
envoie une demande de canal pour demander que la commande donnée être invoquée.
Vous êtes désireux d'envoyer une chaîne de texte pour répondre à une invite, ne pas invoquer une commande. Les documents montrent exec
utilisés pour envoyer des commandes CLI complète comme "ls -l / home".
Au lieu de cela, send_data
est probablement ce que vous voulez. Les documents montrent qu'il permet d'envoyer un texte arbitraire, comme channel.send_data("the password\n")
. Notez, cependant, cette phrase dans la documentation:
Notez qu'il n'envoie pas immédiatement les données à travers le canal, mais au lieu simplement les données concatène données à la mémoire tampon de sortie du canal, préparatoire à être emballé et envoyé la prochaine fois que la connexion accepte les données.
Vous pouvez jeter un oeil à channel.request_pty
. Il semble être conçu pour l'interaction avec une application basée sur la console.
Si vous essayez de (en substance) le scénario d'une session SSH que vous le feriez normalement manuellement, vous trouverez peut-être plus facile d'utiliser une interface comme expect
(par exemple, un petit bijou comme sshExpect pourrait être la peine d'essayer).
Autres conseils
Merci à tous pour les pointeurs. Je suis en mesure de mettre le doigt sur le problème - en plus d'utiliser channel.request_pty il était également nécessaire de demander une coquille. Ce qui suit fonctionne finalement comme prévu:
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
Je ne connais pas terriblement avec les libs Net :: SSH, donc je ne peux pas aider que par-soi, mais il semble que vous pouvez obtenir ce que vous voulez en utilisant Capistrano .
Par exemple, j'ai une tâche de Capistrano qui se connecte à un serveur distant, exécute une commande qui attend une entrée et continue ensuite. Capistrano prend soin de la télécommande i / o. Peut-être que cela pourrait être une solution pour vous?
it helps!
Si j'exécute "1\n"
dans une coquille la réponse que je reçois est: bash: 1: command not found
Si j'exécute echo "1"
je reçois: 1
Êtes-vous sûr de vouloir essayer d'exécuter le texte que vous envoyez? Peut-être que vous cherchez quelque chose comme:
output = ""
Net::SSH.start('host', 'user', :password => "pass") do |ssh|
output = ssh.exec! "echo 1"
end
puts output
Je ne suis pas compétent avec qui lib, mais sur SSH vous pouvez ouvrir plusieurs canaux. Peut-être que le serveur répond uniquement au premier canal par défaut et si vous ouvrez un autre vous obtenez une coquille fraîche.