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 :)
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.
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
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)