2008-12-17 7 views
31

J'essaie d'exécuter une commande interactive via paramiko. L'exécution de cmd essaie de demander un mot de passe mais je ne sais pas comment fournir le mot de passe via exec_command de paramiko et l'exécution se bloque. Existe-t-il un moyen d'envoyer des valeurs au terminal si une exécution cmd attend une entrée de manière interactive?Exécution de commandes interactives dans Paramiko

ssh = paramiko.SSHClient() 
ssh.connect(server, username=username, password=password) 
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("psql -U factory -d factory -f /tmp/data.sql") 

Est-ce que quelqu'un sait comment cela peut être résolu? Je vous remercie.

+1

La question est vieux, mais pour les gens qui viennent encore via google search je veux leur donner ceci.La clé est d'obtenir votre propre ** canal ** [Exécuter des commandes interactives en Python via Paramiko Partie 1] (https://www.youtube.com/watch?v=Jc2l- n_GYPI) [Exécution des commandes interactives en Python via Paramiko Partie 2] (https://www.youtube.com/watch?v=lLKdxIu3-A4) Dans ces deux vidéos, il est expliqué comment exécuter des commandes interactives via paramiko en particulier la deuxième vidéo est super et probablement ce dont vous avez besoin. –

Répondre

26

Les pleins navires de distribution de paramiko avec beaucoup de bonne demos.

Dans le sous-répertoire demos, demo.py et interactive.py ont des exemples de TTY interactifs complets qui seraient probablement exagérément adaptés à votre situation. Dans votre exemple ci-dessus ssh_stdin agit comme un objet fichier Python standard, donc ssh_stdin.write devrait fonctionner tant que le canal est toujours ouvert.

Je n'ai jamais eu besoin d'écrire dans stdin, mais les docs suggèrent qu'un canal est fermé dès qu'une commande se termine, donc l'utilisation de la méthode standard stdin.write pour envoyer un mot de passe ne fonctionnera probablement pas. Il y a des commandes paramiko de niveau inférieur sur le canal lui-même qui vous donnent plus de contrôle - voyez comment la méthode SSHClient.exec_command est implémentée pour tous les détails sanglants.

+1

Et, pour ceux d'entre vous qui veulent seulement voir ce que la sortie d'une commande pourrait être, du code pourrait être: '(stdin, stdout, stderr) = Client.exec_command ('ls -la') imprimer ("\ nstdout est: \ n" + stdout.read() + "\ nstderr est: \ n" + stderr.read()) ' –

+1

' SSHClient.exec_command'Link est mort – Ludisposed

+1

Lien rompu fixe. – scy

3

Je ne suis pas familier avec paramiko, mais cela peut fonctionner:

ssh_stdin.write('input value') 
ssh_stdin.flush() 

Pour plus d'informations sur stdin:

http://docs.python.org/library/sys.html?highlight=stdin#sys.stdin

+2

REMARQUE: Veillez toujours à vider() tout tampon que vous écrivez de la façon dont cet exemple s'affiche correctement; Oublier (ou ne pas savoir) de le faire est une cause fréquente de frustration. – aculich

5

Vous avez besoin de Pexpect pour obtenir le meilleur des deux mondes (les wrappers expect et ssh).

6

J'ai eu le même problème en essayant de faire une session SSH interactive en utilisant ssh, une fourche de Paramiko.

Je fouilla et trouvé cet article:

http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/

Pour continuer votre exemple, vous pourriez faire

ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("psql -U factory -d factory -f /tmp/data.sql") 
ssh_stdin.write('password\n') 
ssh_stdin.flush() 
output = ssh_stdout.read() 

L'article va plus en profondeur, décrivant une coquille totalement interactive autour exec_command. J'ai trouvé cela beaucoup plus facile à utiliser que les exemples dans la source.

+1

Le lien est cassé :( –

3
ssh = paramiko.SSHClient() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect(server_IP,22,username, password) 


stdin, stdout, stderr = ssh.exec_command('/Users/lteue/Downloads/uecontrol-CXC_173_6456-R32A01/uecontrol.sh -host localhost ') 
alldata = "" 
while not stdout.channel.exit_status_ready(): 
    solo_line = ""   
    # Print stdout data when available 
    if stdout.channel.recv_ready(): 
     # Retrieve the first 1024 bytes 
     solo_line = stdout.channel.recv(1024) 
     alldata += solo_line 
    if(cmp(solo_line,'uec> ') ==0): #Change Conditionals to your code here 
    if num_of_input == 0 : 
     data_buffer = ""  
     for cmd in commandList : 
     #print cmd 
     stdin.channel.send(cmd)  # send input commmand 1 
     num_of_input += 1 
    if num_of_input == 1 : 
     stdin.channel.send('q \n')  # send input commmand 2 , in my code is exit the interactive session, the connect will close. 
     num_of_input += 1 
print alldata 
ssh.close()    

Pourquoi stdout.read() se bloque si l'utilisation dierectly sans vérifier stdout. channel.recv_ready(): in alors que stdout.channel.exit_status_ready():

Pour mon cas, après l'exécution de la commande sur le serveur distant, la session attend l'entrée de l'utilisateur, après mettre 'q', il va fermer la connexion. Mais avant d'entrer 'q', le stdout.read() va attendre EOF, il semble que cette méthode ne fonctionne pas si le buffer est plus grand.

  • J'ai essayé stdout.read (1) alors que, cela fonctionne
    J'ai essayé stdout.readline() dans tout, cela fonctionne aussi.
    stdin, stdout, stderr = ssh.exec_command ('/ Users/lteue/Téléchargements/uecontrol')
    stdout.read() se bloque
+0

Cela devrait être une question distincte si vous avez besoin d'une réponse (comme il s'agit d'une vieille question) Ou au moins il devrait être un commentaire sur la question ou l'une des réponses.Il ne peut pas être une réponse par lui-même. – Sharmila