Répondre à une invite de SSH avant la première commande avec Ruby et Net :: SSH

StackOverflow https://stackoverflow.com/questions/2223194

  •  19-09-2019
  •  | 
  •  

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

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top