web-dev-qa-db-fra.com

python paramiko ssh

je suis nouveau sur python. j'ai écrit un script pour se connecter à un hôte et exécuter une commande

ssh = paramiko.SSHClient()
ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(Host, username=user, password=pw)

print 'running remote command'

stdin, stdout, stderr = ssh.exec_command(command)
stdin.close()

for line in stdout.read().splitlines():
    print '%s$: %s' % (Host, line)
    if outfile != None:
        f_outfile.write("%s\n" %line)

for line in stderr.read().splitlines():
    print '%s$: %s' % (Host, line + "\n")
    if outfile != None:
        f_outfile.write("%s\n" %line)

ssh.close()

if outfile != None:
    f_outfile.close()

print 'connection to %s closed' %Host

except:
   e = sys.exc_info()[1]
   print '%s' %e

fonctionne bien quand la commande à distance n'a pas besoin d'un terminal. J'ai trouvé un exemple invoke_Shell Session SSH imbriquée avec Paramiko . cette solution ne me convient pas, car si un serveur a une invite qui n'est pas spécifiée dans mon script -> boucle infinie ou une invite spécifiée dans le script est une chaîne dans le texte de retour -> toutes les données ne seront pas reçues . Existe-t-il une meilleure solution, peut-être où stdout et stderr sont renvoyés comme dans mon script?

13
user1008764

Vous trouverez une documentation complète sur l'API paramiko à l'adresse suivante: http://docs.paramiko.org/fr/stable/index.html

J'utilise la méthode suivante pour exécuter des commandes sur un client protégé par mot de passe:

import paramiko
import sys

nbytes = 4096
hostname = 'hostname'
port = 22
username = 'username' 
password = 'password'
command = 'ls'

client = paramiko.Transport((hostname, port))
client.connect(username=username, password=password)

stdout_data = []
stderr_data = []
session = client.open_channel(kind='session')
session.exec_command(command)
while True:
    if session.recv_ready():
        stdout_data.append(session.recv(nbytes))
    if session.recv_stderr_ready():
        stderr_data.append(session.recv_stderr(nbytes))
    if session.exit_status_ready():
        break

print 'exit status: ', session.recv_exit_status()
print ''.join(stdout_data)
print ''.join(stderr_data)

session.close()
client.close()
16
ThePracticalOne

Il y a quelque chose qui ne va pas avec la réponse acceptée, elle apporte parfois (de manière aléatoire) une réponse tronquée du serveur. Je ne sais pas pourquoi, je n'ai pas enquêté sur la cause défectueuse de la réponse acceptée car ce code fonctionnait parfaitement pour moi:

import paramiko

ip='server ip'
port=22
username='username'
password='password'

cmd='some useful command' 

ssh=paramiko.SSHClient()
ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,password)

stdin,stdout,stderr=ssh.exec_command(cmd)
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp)

stdin,stdout,stderr=ssh.exec_command('some really useful command')
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp)
12
Raiden Core

Le code de @ThePracticalOne est idéal pour afficher l'utilisation, sauf pour une chose: Parfois la sortie serait incomplète. (session.recv_ready() devient vrai après la if session.recv_ready():, alors que session.recv_stderr_ready() et session.exit_status_ready() sont devenus vrais avant d'entrer dans la boucle suivante)

je pense donc à récupérer les données quand elles seront prêtes à quitter la session.

while True:
if session.exit_status_ready():
while True:
    while True:
        print "try to recv stdout..."
        ret = session.recv(nbytes)
        if len(ret) == 0:
            break
        stdout_data.append(ret)

    while True:
        print "try to recv stderr..."
        ret = session.recv_stderr(nbytes)
        if len(ret) == 0:
            break
        stderr_data.append(ret)
    break
0
David McRay