Mettre en œuvre un shell interactif via ssh en Python à l'aide de Paramiko?
Je veux écrire un programme en Python 3.x sur Windows 7) qui exécute plusieurs commandes dans un shell à distance via ssh. Après avoir regardé paramikos' exec_command fonction de (), j'ai réalisé qu'il ne soit pas adapté à mon cas d'utilisation (parce que le canal est fermé après l'exécution de la commande), comme les commandes dépendent de variables d'environnement (mis en avant les commandes) et ne peuvent être concaténées dans une exec_command() l'appel car ils sont à exécuter à des moments différents dans le programme.
Donc, je veux exécuter des commandes sur le même canal. L'option suivante je l'ai regardé en était la mise en œuvre d'un shell interactif à l'aide de paramikos' invoke_shell() fonction:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=user, password=psw, port=22)
channel = ssh.invoke_shell()
out = channel.recv(9999)
channel.send('cd mivne_final\n')
channel.send('ls\n')
while not channel.recv_ready():
time.sleep(3)
out = channel.recv(9999)
print(out.decode("ascii"))
channel.send('cd ..\n')
channel.send('cd or_fail\n')
channel.send('ls\n')
while not channel.recv_ready():
time.sleep(3)
out = channel.recv(9999)
print(out.decode("ascii"))
channel.send('cd ..\n')
channel.send('cd simulator\n')
channel.send('ls\n')
while not channel.recv_ready():
time.sleep(3)
out = channel.recv(9999)
print(out.decode("ascii"))
ssh.close()
Il y a quelques problèmes avec ce code:
- La première "imprimer" ne donne pas toujours l'impression de le " ls "de sortie (parfois, il est imprimé uniquement sur le deuxième "imprimer").
- Le premier " cd " et " ls "les commandes sont toujours présents dans la sortie (je les obtenir via le "recv " commande", dans le cadre de la sortie), alors que tous la suite de " cd " et " ls " les commandes sont imprimées parfois, et parfois ils ne le sont pas.
- Le deuxième et le troisième " cd " et " ls "commandes (lors de l'impression) apparaissent toujours avant le premier" ls " de sortie.
Je suis confus avec ce "non-déterminisme" et serions très reconnaissants de votre aide.
Avez-vous d'utiliser
paramiko
? Je l'ai trouvé beaucoup plus facile de travailler avec fabric
. Vous venez de configurer env
des variables comme user
, password
et host_string
et ensuite vous pouvez faire diverses choses comme l'utilisation: get
télécharger des fichiers à partir de l'hôte distant, put
envoyer des fichiers et des run
pour émettre des commandes. Vous pouvez enchaîner des commandes comme ceci par exemple: run('cd .. && cd simulator && ls')
.malheureusement, le tissu n'est pas compatible avec python 3.x il n'est donc pas une option. De toute façon, d'après ce que j'ai vu, le Tissu est juste un wrapper pour paramiko et ne me permet pas de courir "non-enchaînée" les commandes dans le même canal. Il y a beaucoup de logique que j'ai finalement envie de courir entre les commandes du shell.
désolé, j'ai oublié que vous travaillez avec Python 3.x
découvrez netmiko Elle est spécialisée pour les périphériques réseau, mais vous pouvez également l'utiliser avec Linux. Il fonctionne sur Python 3 et est construit sur Paramiko, mais aussi de s'occuper beaucoup de la mise en mémoire tampon pour vous
OriginalL'auteur misha | 2016-03-05
Vous devez vous connecter pour publier un commentaire.
Pouvez-vous me montrer le code?
Que faire si j'ai ma commande de produit à la fois la sortie standard stdout et stderr, et je veux les en tant que fichiers distincts?
Je ne l'ai pas essayé, mais je pense que vous pourriez déclarer l'auto.stderr = canal.makefile_stderr ("r"), d'une manière similaire à la façon dont stdin et stdout sont déclarées (attention à la makefile_stderr méthode). Alors, soi-disant, vous pouvez accéder stderr que le fichier-comme l'objet doit être associé avec le stderr de ce canal.
vous pouvez éviter de doit de le stdout de nettoyage par: - la suppression de l'invite de commande par l'envoi d'cmd "export PS1="\n"" - éviter écho stdin par l'envoi d'cmd "stty -echo"
OriginalL'auteur misha
Je suis à la base à l'aide de tout votre code et simplement l'ajout d'une boucle for:
Il exécute 2 commandes, avec le bon de sortie, mais alors il se trouve juste là. Je me demande si j'ai besoin d'appeler del quelque part dans le code.
On dirait qu'il n'a pas de retour. Si j'ai in, out, err = conn_one.execute(commande) print(in,out et err) je ne suis pas d'obtenir quelque chose en retour. Suis-je censé être l'appel de la ssh.close() dans le code de retour de la boucle?
Non, vous n'êtes pas censé être l'appel à close(). Pourriez-vous me dire exactement les commandes que vous essayez de les exécuter?
Je vous suggère de vérifier si l'une des commandes que vous essayez d'exécuter n'est pas de retour, car il ouvre une interface graphique ou certains de dialogue qui nécessite une entrée supplémentaire avant la fin. Vous pouvez également essayer d'exécuter ces commandes dans un shell unix et voir ce qui se passe dans le terminal.
J'ai ajouté un print(str(ligne)) à droite après la ligne de l'auto.stdout: pour voir le résultat et si je ajouter un compteur à ce point count = count + 1 et de briser cela fonctionne. Par exemple, si j'ai 4 commandes à exécuter que j'ai: si compteur==4: pause puis je vois que tous les 4 commandes ont été exécutées, C'est exactement ce dont j'avais besoin.
OriginalL'auteur magicsword