Was ist der einfachste Weg zu SSH mit Python?

82

Wie kann ich einfach von einem lokalen Python (3.0) -Skript aus SSH an einen Remote-Server senden, ein Login / Passwort eingeben, einen Befehl ausführen und die Ausgabe auf der Python-Konsole drucken?

Ich würde lieber keine große externe Bibliothek verwenden oder irgendetwas auf dem Remote-Server installieren.

Christopher Tokar
quelle

Antworten:

42

Ich habe es nicht ausprobiert, aber dieses Pysftp- Modul könnte helfen, das wiederum paramiko verwendet. Ich glaube, alles ist clientseitig.

Der interessante Befehl ist wahrscheinlich der, .execute()der einen beliebigen Befehl auf dem Remote-Computer ausführt. (Das Modul bietet auch Funktionen .get()und .putMethoden, die mehr auf seinen FTP-Charakter verweisen.)

AKTUALISIEREN:

Ich habe die Antwort neu geschrieben, nachdem der Blog-Beitrag, auf den ich ursprünglich verlinkt habe, nicht mehr verfügbar ist. Einige der Kommentare, die sich auf die alte Version dieser Antwort beziehen, sehen jetzt seltsam aus.

ThomasH
quelle
Guter Fund! Solange Sie sich nicht für das Anpassen von Fehlerantworten interessieren, wäre diese zusätzliche Abstraktion sehr nützlich.
Cascabel
Das ssh-Modul hat es geschafft. Einfach und funktioniert gut. Kein Durchsuchen der Paramiko-API.
Christopher Tokar
2
Der Link zur Datei ssh.py in dem von Ihnen angegebenen Link ist
fehlerhaft
Ja, können wir bitte einen neuen Link haben? Ich habe ssh.py auf github gefunden, aber es ist nicht dasselbe (und nicht so gut)
joedborg
1
Das pysftp-Paket bietet nur SFTP. Weit entfernt von einem SSH-Client.
Bortzmeyer
61

Sie können es selbst mit Paramiko codieren, wie oben vorgeschlagen. Alternativ können Sie sich Fabric ansehen, eine Python-Anwendung, mit der Sie alle Aufgaben ausführen können, nach denen Sie gefragt haben:

Fabric ist eine Python-Bibliothek und ein Befehlszeilentool zur Optimierung der Bereitstellung von Anwendungen oder zur Ausführung von Systemverwaltungsaufgaben über das SSH-Protokoll. Es bietet Tools zum Ausführen beliebiger Shell-Befehle (entweder als normaler Anmeldebenutzer oder über sudo), zum Hochladen und Herunterladen von Dateien usw.

Ich denke, das passt zu Ihren Bedürfnissen. Es ist auch keine große Bibliothek und erfordert keine Serverinstallation, obwohl es Abhängigkeiten von paramiko und pycrypt gibt, die eine Installation auf dem Client erfordern.

Die App war früher hier . Es kann jetzt hier gefunden werden .

* The official, canonical repository is git.fabfile.org
* The official Github mirror is GitHub/bitprophet/fabric

Es gibt mehrere gute Artikel darüber, obwohl Sie vorsichtig sein sollten, da es sich in den letzten sechs Monaten geändert hat:

Bereitstellen von Django mit Fabric

Werkzeuge des modernen Python-Hackers: Virtualenv, Fabric und Pip

Einfache und einfache Bereitstellung mit Fabric und Virtualenv


Später: Für die Installation von Fabric ist paramiko nicht mehr erforderlich:

$ pip install fabric
Downloading/unpacking fabric
  Downloading Fabric-1.4.2.tar.gz (182Kb): 182Kb downloaded
  Running setup.py egg_info for package fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
Downloading/unpacking ssh>=1.7.14 (from fabric)
  Downloading ssh-1.7.14.tar.gz (794Kb): 794Kb downloaded
  Running setup.py egg_info for package ssh
Downloading/unpacking pycrypto>=2.1,!=2.4 (from ssh>=1.7.14->fabric)
  Downloading pycrypto-2.6.tar.gz (443Kb): 443Kb downloaded
  Running setup.py egg_info for package pycrypto
Installing collected packages: fabric, ssh, pycrypto
  Running setup.py install for fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
    Installing fab script to /home/hbrown/.virtualenvs/fabric-test/bin
  Running setup.py install for ssh
  Running setup.py install for pycrypto
...
Successfully installed fabric ssh pycrypto
Cleaning up...

Dies ist jedoch meistens kosmetischer Natur: ssh ist eine Abzweigung von paramiko, der Betreuer für beide Bibliotheken ist der gleiche (Jeff Forcier, ebenfalls der Autor von Fabric), und der Betreuer hat Pläne, paramiko und ssh unter dem Namen paramiko wieder zusammenzuführen . (Diese Korrektur über pbanka .)

hughdbrown
quelle
Da dies ein interessanter Link zu sein scheint, möchte ich ihn aktualisieren, da Ihr Link jetzt defekt ist. Bitte benutzen Sie: clemesha.org/blog/…
dlewin
Hat der Fragesteller nicht angegeben, dass er keine "große externe Bibliothek" verwenden möchte? Paramiko und Fabric sind beide übertrieben, wenn der Autor nur ein einfaches, einmaliges SSH-Rezept verlangt.
Zoran Pavlovic
1
@Zoran Pavlovic: Alle Antworten waren entweder die Installation eines lokalen Pakets (paramiko, Fabric, ssh, libssh2) oder die Verwendung eines Unterprozesses zum Ausführen von ssh. Letzteres ist eine Lösung ohne Installation, aber ich denke nicht, dass das Laichen von ssh eine großartige Idee ist, und das OP auch nicht, da er die Antwort für die Installation des ssh-Moduls ausgewählt hat. Diese Dokumente sagen: "ssh.py bietet drei gängige SSH-Operationen: Abrufen, Setzen und Ausführen. Es handelt sich um eine Abstraktion auf hoher Ebene für Paramiko." Wenn Sie also libssh2 nicht bevorzugen, das viel Codierung erfordert, gibt es keine konforme Empfehlung. Ich bevorzuge eine gute Lösung, wenn die Bedingungen des OP nicht angemessen erfüllt werden können.
Hughdbrown
24

Wenn Sie zusätzliche Module vermeiden möchten, können Sie das Unterprozessmodul zum Ausführen verwenden

ssh [host] [command]

und erfassen Sie die Ausgabe.

Versuchen Sie etwas wie:

process = subprocess.Popen("ssh example.com ls", shell=True,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output,stderr = process.communicate()
status = process.poll()
print output

Um mit Benutzernamen und Kennwörtern umzugehen, können Sie einen Unterprozess verwenden, um mit dem ssh-Prozess zu interagieren, oder Sie können einen öffentlichen Schlüssel auf dem Server installieren, um die Kennwortabfrage zu vermeiden.

Neil
quelle
7
Aber was ist, wenn der Client unter Windows läuft?
Nathan
Es kann schwierig sein, ein Kennwort für den sshUnterprozess über eine Pipe anzugeben. Siehe Warum nicht einfach eine Pipe (popen ()) verwenden? . Möglicherweise müssen pty, pexpectModule , die es zu umgehen.
JFS
scheint nicht für den String 'ssh somecomputer zu funktionieren; python -c "import numpy; print numpy .__ version__" 'es sagt, dass es den Befehl "import" nicht
kennt
1
@usethedeathstar: Umschließen Sie den gesamten Remote-Befehl in Anführungszeichen: ssh somecomputer 'python -c "import this; print this"'
Neil
17

Ich habe Python-Bindungen für libssh2 geschrieben . Libssh2 ist eine clientseitige Bibliothek, die das SSH2-Protokoll implementiert.

import socket
import libssh2

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('exmaple.com', 22))

session = libssh2.Session()
session.startup(sock)
session.userauth_password('john', '******')

channel = session.channel()
channel.execute('ls -l')

print channel.read(1024)
Sebastian Noack
quelle
2
Es scheint sehr niedrig zu sein. Zum Beispiel (Ihr eigenes Beispiel) müssen Sie explizit sagen, dass Sie IPv4 oder IPv6 verwenden (etwas, das Sie nicht mit dem OpenSSH-Befehlszeilenclient zu tun haben). Außerdem habe ich nicht herausgefunden, wie es mit dem ssh-Agenten funktioniert.
Bortzmeyer
2
Das Gute an pylibssh2 ist, dass es Dateien viel schneller überträgt als jede native Python-Implementierung von ssh wie paramiko.
Damien
8

Ihre Definition von "am einfachsten" ist hier wichtig - einfacher Code bedeutet die Verwendung eines Moduls (obwohl "große externe Bibliothek" übertrieben ist).

Ich glaube, das aktuellste (aktiv entwickelte) Modul ist paramiko . Es enthält Demoskripte im Download und eine detaillierte Online-API-Dokumentation. Sie können auch PxSSH ausprobieren , das in pexpect enthalten ist . Es gibt ein kurzes Beispiel zusammen mit der Dokumentation unter dem ersten Link.

Beachten Sie auch in Bezug auf die Einfachheit, dass eine gute Fehlererkennung Ihren Code immer komplexer erscheinen lässt. Sie sollten jedoch in der Lage sein, viel Code aus den Beispielskripten wiederzuverwenden und ihn dann zu vergessen.

Cascabel
quelle
6

Wie Hughbrown mag ich Stoff. Bitte beachten Sie, dass es zwar ein eigenes deklaratives Scripting implementiert (für Bereitstellungen und dergleichen), aber auch als Python-Modul importiert und in Ihren Programmen verwendet werden kann, ohne ein Fabric-Skript schreiben zu müssen.

Fabric hat einen neuen Betreuer und wird gerade neu geschrieben. Das bedeutet, dass die meisten Tutorials, die Sie (derzeit) im Web finden, mit der aktuellen Version nicht funktionieren. Außerdem zeigt Google weiterhin die alte Fabric-Seite als erstes Ergebnis an.

Aktuelle Dokumentationen finden Sie unter: http://docs.fabfile.org

Juanjux
quelle
Fabric verwendet eine Gabel von paramiko pypi.python.org/pypi/ssh für alle ssh-Sachen.
Damien
6

Ich fand, dass paramiko etwas zu niedrig ist und Fabric nicht besonders gut für die Verwendung als Bibliothek geeignet ist. Deshalb habe ich meine eigene Bibliothek namens spur zusammengestellt , die paramiko verwendet, um eine etwas schönere Oberfläche zu implementieren:

import spur

shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
result = shell.run(["echo", "-n", "hello"])
print result.output # prints hello

Sie können auch festlegen, dass die Ausgabe des Programms während der Ausführung gedruckt wird. Dies ist hilfreich, wenn Sie die Ausgabe lang laufender Befehle vor dem Beenden anzeigen möchten:

result = shell.run(["echo", "-n", "hello"], stdout=sys.stdout)
Michael Williamson
quelle
Unterstützt nicht das Ausführen von nicht standardmäßigen Befehlen, z. B. auf einigen Routern (MikroTik). Befehlen wird das Präfix '/' vorangestellt. Diese Bibliothek gibt einen Fehler aus. Für Standard-Linux-Hosts scheint es jedoch ziemlich gut zu sein.
Babken Vardanyan
Wenn ich eine IP-Adresse an den Hostnamen übergebe, wird ein Fehler ausgegeben, der besagt, dass die IP in bekannten_Hosts nicht gefunden wurde ...
Rexbelia
@rexbelia Dies ist das normale Verhalten von SSH: Um sicherzustellen, dass Sie mit dem richtigen Server sprechen, akzeptiert SSH den Schlüssel nur von einem Host, wenn er bereits bekannt ist. Die Lösung besteht entweder darin, den relevanten Schlüssel zu bekannten_Hosts hinzuzufügen oder das Argument für den fehlenden_Host_schlüssel auf einen geeigneten Wert zu setzen, wie in der Dokumentation beschrieben.
Michael Williamson
4

Für diejenigen, die hier ankommen und nach Python-SSH-Beispiel googeln. Die ursprüngliche Frage und Antwort ist jetzt fast eine Dekodierung alt. Es scheint, dass der Paramiko einige Funktionen erhalten hat (Ok. Ich gebe zu - ich vermute hier - ich bin neu in Python) und Sie können den SSH-Client direkt mit dem Paramiko erstellen.

import base64
import paramiko

client = paramiko.SSHClient()

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.1.1', username='user', password='password')
stdin, stdout, stderr = client.exec_command('cat /proc/meminfo')
for line in stdout:
    print('... ' + line.strip('\n'))
client.close()

Dieser Code wurde aus der Demo von https://github.com/paramiko/paramiko angepasst. Es funktioniert für mich.

oceanuz
quelle
1

Das hat bei mir funktioniert

import subprocess
import sys
HOST="IP"
COMMAND="ifconfig"

def passwordless_ssh(HOST):
        ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
                       shell=False,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)
        result = ssh.stdout.readlines()
        if result == []:
                error = ssh.stderr.readlines()
                print >>sys.stderr, "ERROR: %s" % error
                return "error"
        else:
                return result
Naveen
quelle
1

please refer to paramiko.org, its very useful while doing ssh using python.

import paramiko

import time

ssh = paramiko.SSHClient() #SSHClient() is the paramiko object</n>

#Below lines adds the server key automatically to know_hosts file.use anyone one of the below

ssh.load_system_host_keys() 

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:

#Here we are actually connecting to the server.

ssh.connect('10.106.104.24', port=22, username='admin', password='')

time.sleep(5)

#I have mentioned time because some servers or endpoint prints there own information after 
#loggin in e.g. the version, model and uptime information, so its better to give some time 
#before executing the command.

#Here we execute the command, stdin for input, stdout for output, stderr for error

stdin, stdout, stderr = ssh.exec_command('xstatus Time')

#Here we are reading the lines from output.

output = stdout.readlines() 

print(output)


#Below all are the Exception handled by paramiko while ssh. Refer to paramiko.org for more information about exception.


except (BadHostKeyException, AuthenticationException,  
    SSHException, socket.error) as e:           

print(e)
Harshan Gowda
quelle
0

Schauen Sie sich spurplus an , einen Wrapper um spur und paramiko , den wir entwickelt haben, um Remotecomputer zu verwalten und Dateivorgänge auszuführen.

Spurplus bietet eine sofort einsatzbereite check_output()Funktion:

import spurplus
with spurplus.connect_with_retries(
        hostname='some-machine.example.com', username='devop') as shell:
     out = shell.check_output(['/path/to/the/command', '--some_argument']) 
     print(out)
marko.ristin
quelle