2012-05-24 22 views
10

soy nuevo en python. Escribí un guión para conectarse a un host y ejecutar un comandopython paramiko ssh

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 

funciona bien cuando el entonces comando remoto no necesita un TTY. Encontré un ejemplo de invoke_shell Nested SSH session with Paramiko. No estoy contento con esta solución, porque si un servidor tiene un mensaje que no está especificado en mi script -> ciclo infinito o un mensaje específico en el script es una cadena en el texto de retorno -> no se recibirán todos los datos . ¿Hay alguna solución mejor en la que se envíen stdout y stderr como en mi script?

Respuesta

11

Existe una extensa documentación de la API paramiko se puede encontrar en: http://docs.paramiko.org/en/stable/index.html

utilizo el siguiente método para ejecutar comandos en una contraseña de cliente protegida:

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() 
+1

en lugar de 'data_block' uno debe utilizar' session.recv (4096) 'y' session.recv_stderr (4096) 'por ejemplo (¿de dónde vienen del' data_block'?). –

+0

Tiene razón, el bloque de datos era como describió (recv/recv_stderr) pero borré esas líneas por accidente. – ThePracticalOne

+0

A partir de mayo de 2015, los documentos de Paramiko están [aquí] (http://docs.paramiko.org/en/1.15/index.html) – Jeremiah

7

Hay algo malo con la respuesta aceptada, a veces (al azar) trae una respuesta recortada del servidor. No sé por qué, no investigó la causa defectuosa de la respuesta aceptada, porque este código funcionó a la perfección para mí:

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) 
+0

También he visto esto, es como una condición de carrera w/exit_status_ready() y recv_ready() – robert

0

El código de @ThePracticalOne es grande para mostrar el uso excepto por una cosa: somtimes la salida sería incompleta. (session.recv_ready() resulta cierto después de la if session.recv_ready(): mientras session.recv_stderr_ready() y session.exit_status_ready() resultó cierto antes de entrar en la próxima circular)

por lo que mi pensamiento es recuperar los datos cuando está listo para salir de la sesión.

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 
Cuestiones relacionadas