it-swarm.com.de

python paramiko ssh

ich bin neu in Python. Ich schrieb ein Skript, um eine Verbindung zu einem Host herzustellen und einen Befehl auszuführen

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

funktioniert gut, wenn der Fernbefehl kein tty benötigt. Ich fand ein invoke_Shell-Beispiel Verschachtelte SSH-Sitzung mit Paramiko . Ich bin mit dieser Lösung nicht zufrieden, denn wenn ein Server über eine Eingabeaufforderung verfügt, die nicht in meinem Skript angegeben ist -> Endlosschleife oder eine angegebene Eingabeaufforderung im Skript ist eine Zeichenfolge im Rückgabetext -> werden nicht alle Daten empfangen . Gibt es eine bessere Lösung, wenn stdout und stderr wie in meinem Skript zurückgeschickt werden?

13
user1008764

Eine umfangreiche Paramiko-API-Dokumentation finden Sie unter: http://docs.paramiko.org/de/stable/index.html

Ich verwende die folgende Methode, um Befehle auf einem passwortgeschützten Client auszuführen:

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

Die akzeptierte Antwort stimmt nicht, sie bringt manchmal (zufällig) eine abgeschnittene Antwort vom Server. Ich weiß nicht warum, ich habe die fehlerhafte Ursache der akzeptierten Antwort nicht untersucht, weil dieser Code für mich perfekt funktioniert hat:

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

Der Code von @ThePracticalOne eignet sich hervorragend zum Anzeigen der Verwendung mit einer Ausnahme: Manchmal Die Ausgabe wäre unvollständig. (session.recv_ready() wird nach der if session.recv_ready(): auf true gesetzt, während session.recv_stderr_ready() und session.exit_status_ready() vor dem Eintritt in die nächste Schleife auf true gesetzt wurden.

daher denke ich daran, die Daten abzurufen, wenn sie zum Beenden der Sitzung bereit sind.

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