web-dev-qa-db-fra.com

obtenir la sortie d'un paramiko ssh exec_command en continu

J'exécute un script python de longue durée via ssh sur une machine distante à l'aide de paramiko. Fonctionne comme un charme, pas de problèmes jusqu'à présent. 

Malheureusement, les stdout (respectivement stderr) ne sont affichées qu'une fois le script terminé! Cependant, en raison du temps d’exécution, je préférerais de beaucoup que produise chaque nouvelle ligne telle qu’elle est imprimée , pas après. 

remote = paramiko.SSHClient()
remote.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
remote.connect("Host", username="uname", password="pwd")

# myScript produces continuous output, that I want to capture as it appears    
stdin, stdout, stderr = remote.exec_command("python myScript.py")
stdin.close()
for line in stdout.read().splitlines():
    print(line)

Comment cela peut il etre accompli? Note: Bien sûr, la sortie pourrait être dirigée vers un fichier et «moins» ce fichier via une autre session ssh, mais c'est très moche et j'ai besoin d'une solution plus propre, idéalement Pythonic :)

14
Lukas N.P. Egger

Comme spécifié dans la documentation read ([size]) , si vous ne spécifiez pas une variable size, elle lit jusqu'à EOF, ce qui fait que le script attend la fin de la commande avant de retourner de read() et d'imprimer sortie.

Vérifiez cette réponse: Comment faire une boucle jusqu'à EOF en Python? et Comment faire un "While not not EOF" pour obtenir des exemples sur la manière d'épuiser l'objet de type File.

9
KurzedMetal

Un exemple de travail minimal et complet sur l’utilisation de cette réponse (testé en Python 3.6.1)

# run.py
from paramiko import SSHClient

ssh = SSHClient()
ssh.load_system_Host_keys()

ssh.connect('...')

print('started...')
stdin, stdout, stderr = ssh.exec_command('python -m example', get_pty=True)

for line in iter(stdout.readline, ""):
    print(line, end="")
print('finished.')

et

# example.py, at the server
import time

for x in range(10):
    print(x)
    time.sleep(2)

exécuter sur la machine locale avec 

python -m run
7
Jorge Leitão

Je faisais face à un problème similaire. J'ai pu le résoudre en ajoutant get_pty = True à paramiko:

stdin, stdout, stderr = client.exec_command("/var/mylongscript.py", get_pty=True)
7
James Shrum