2008-10-30 14 views
122

Was ist der pythischste Weg, um eine Datei in Python zu scannen? Der einzige Weg, den ich bewusst bin, istWie scp in Python?

os.system('scp "%s" "%s:%s"' % (localfile, remotehost, remotefile)) 

, die einen Hack ist, und welche außerhalb Linux-ähnlichen Systemen nicht funktioniert, und die Hilfe vom Pexpect Modul benötigt Passwort zu vermeiden, fordert, wenn Sie bereits passwordless haben SSH für den Remote-Host eingerichtet.

Ich kenne Twisted conch, aber ich würde es vorziehen, scp selbst zu implementieren über Low-Level-ssh-Module.

Ich kenne paramiko, ein Python-Modul, das ssh und sftp unterstützt; aber es unterstützt nicht scp.

Hintergrund: Ich bin eine Verbindung zu einem Router, der sftp nicht unterstützt, aber unterstützt ssh/scp, so sftp ist keine Option.

BEARBEITEN: Dies ist ein Duplikat von How to copy a file to a remote server in Python using SCP or SSH?. Allerdings, diese Frage gibt keine scp-spezifische Antwort, die Schlüssel aus Python behandelt. Ich hoffe auf eine Art und Weise Code Art zu laufen wie

import scp 

client = scp.Client(host=host, user=user, keyfile=keyfile) 
# or 
client = scp.Client(host=host, user=user) 
client.use_system_keys() 
# or 
client = scp.Client(host=host, user=user, password=password) 

# and then 
client.transfer('/etc/local/filename', '/etc/remote/filename') 

Antwort

4

Wenn Sie Putty auf Win32 installieren, erhalten Sie einen Pscp (Putty Scp).

so können Sie den os.system Hack auf Win32 zu verwenden.

(und Sie können den Kitt-Mittel für Schlüsselmanagement verwenden)


leider ist es nur ein Hack (aber man kann es in einer Python-Klasse wickeln)

+0

Der einzige Grund, der 'nix funktioniert, ist, haben Sie SCP auf dem Weg; wie Blauohr betont, ist das nicht schwer zu beheben. +1 – ojrac

12

Vielleicht haben Sie interessiert an versuchen Pexpect (SourceForge project). Auf diese Weise können Sie interaktive Eingabeaufforderungen für Ihr Kennwort bearbeiten.

Hier ist ein Schnipsel von Beispiel Nutzung (für ftp) von der Haupt-Website:

 
    # This connects to the openbsd ftp site and 
    # downloads the recursive directory listing. 
    import pexpect 
    child = pexpect.spawn ('ftp ftp.openbsd.org') 
    child.expect ('Name .*: ') 
    child.sendline ('anonymous') 
    child.expect ('Password:') 
    child.sendline ('[email protected]') 
    child.expect ('ftp> ') 
    child.sendline ('cd pub') 
    child.expect('ftp> ') 
    child.sendline ('get ls-lR.gz') 
    child.expect('ftp> ') 
    child.sendline ('bye') 
1

Hmmm, vielleicht eine andere Möglichkeit wäre, so etwas wie sshfs (es ein sshfs für Mac auch) zu verwenden. Sobald Ihr Router gemountet ist, können Sie die Dateien einfach kopieren. Ich bin nicht sicher, ob das für Ihre spezielle Anwendung funktioniert, aber es ist eine nette Lösung, um handlich zu bleiben.

8

Sie können auch paramiko überprüfen. Es gibt (noch) kein scp-Modul, aber es unterstützt vollständig sftp.

[EDIT] Sorry, verpasste die Zeile, wo Sie Paramiko erwähnt. Das folgende Modul ist einfach eine Implementierung des scp-Protokolls für Paramiko. Wenn Sie nicht paramiko oder conch (die einzige ssh-Implementierungen, die ich für Python weiß) verwenden möchten, könnten Sie dies über eine normale SSH-Sitzung mit Pipes überarbeiten.

scp.py for paramiko

+0

Willst du damit sagen, dass die angehängte Lösung Dateien sicher auf jeden Rechner mit sshd überträgt, auch wenn sftpd nicht läuft? Das ist genau das, wonach ich suche, aber ich kann nicht aus deinem Kommentar sagen, ob das nur SFTP in eine scp-artige Fassade bringt. –

+2

Dies wird Dateien mit jedem Computer mit sshd übertragen, die scp im PATH (scp ist nicht Teil der SSH-Spezifikation, aber es ist ziemlich allgegenwärtig). Dies ruft "scp -t" auf dem Server auf und verwendet das scp-Protokoll, um Dateien zu übertragen, was nichts mit sftp zu tun hat. – JimB

+1

Bitte beachten Sie, dass ich die OpenSSH-Implementierung von scp als Modell verwendet habe, so dass die Zusammenarbeit mit anderen Versionen nicht garantiert ist. Einige Versionen von sshd können auch das scp2-Protokoll verwenden, das im Prinzip dasselbe wie sftp ist. – JimB

76

Versuchen Sie das Modul paramiko_scp. Es ist sehr einfach zu bedienen. Siehe das folgende Beispiel:

def createSSHClient(server, port, user, password): 
    client = paramiko.SSHClient() 
    client.load_system_host_keys() 
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
    client.connect(server, port, user, password) 
    return client 

ssh = createSSHClient(server, port, user, password) 
scp = SCPClient(ssh.get_transport()) 

Dann rufen scp.get() oder scp.put() scp Operationen zu tun.

(SCPClient code)

+0

Außer diesem Modul nicht wirklich paramiko verwenden - es ist eine Menge Code, der für 'scp' am Ende tatsächlich endet die' scp' Kommandozeile aufrufen, die nur auf * nix funktioniert. –

+2

@Nick Bastin, funktionierte großartig für mich auf Linux und Windows –

+7

Vereinbart, was Sie im Quellcode sehen, ist der Remote-Aufruf zu 'scp-t' oder' scp -f' ('zu' und 'von' Modi, die für diesen serverseitigen Zweck existieren).Dies ist im Wesentlichen, wie scp funktioniert - es beruht auf einer anderen Kopie von scp, die auf dem Server existiert. Dieser Artikel erklärt es sehr gut: https://blogs.oracle.com/janp/entry/how_the_scp_protocol_works – laher

2

Werfen Sie einen Blick auf fabric. Ein Beispiel kann here gefunden werden.

+2

Könnten Sie genauer sein? –

1

Ich habe vor einiger Zeit ein Python SCP-Skript erstellt, das auf Paramiko basiert. Es enthält Code zum Verarbeiten von Verbindungen mit einem privaten Schlüssel oder SSH-Schlüsselagenten mit einem Rückfall zur Kennwortauthentifizierung.

http://code.activestate.com/recipes/576810-copy-files-over-ssh-using-paramiko/

+0

Danke für den Link und für die Zeit, um ein gutes Beispiel für die Verwendung von Paramiko zu veröffentlichen. –

0

Wenn Sie auf * nix sind, können Sie sshpass verwenden

sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path 
3

Es ist eine ganze Weile gewesen, da diese Frage gestellt wurde, und in der Zwischenzeit kann eine andere Bibliothek, die damit umgehen hat auftauchten: Sie die copy Funktion in der Plumbum Bibliothek enthalten können:

import plumbum 
r = plumbum.machines.RemoteMachine("example.net", 
user="username", keyfile=".ssh/some_key") 
fro = plumbum.local.path("some_file") 
to = r.path("/path/to/destination/") 
plumbum.path.utils.copy(fro, to) 
+0

Wie kann ich die Passphrase für den privaten Schlüssel mit Plumbum eingeben? p – ekta

+0

@ekta: Sie werden in der Befehlszeile dazu aufgefordert. Wenn Sie es von Ihrem eigenen Code bereitstellen möchten, glaube ich nicht, dass die API von plumbum dies unterstützt. Aber "SshMachine" von Plumbum hat Zugriff auf 'ssh-agent'. Wenn Sie es also einfach vermeiden wollen, es jedes Mal einzugeben, ist das eine Möglichkeit. Sie können auch eine Feature-Anfrage auf der github-Seite von plumbum ablegen. – pmos

4

Konnte keine direkte Antwort finden, und dieses Modul "scp.Client" existiert nicht. Stattdessen this paßt zu mir:

from paramiko import SSHClient 
from scp import SCPClient 

ssh = SSHClient() 
ssh.load_system_host_keys() 
ssh.connect('example.com') 

with SCPClient(ssh.get_transport()) as scp: 
    scp.put('test.txt', 'test2.txt') 
    scp.get('test2.txt') 
2

Sie das Paket subprocess verwenden kann, und den Befehl Aufruf den Befehl scp aus der Schale zu verwenden.

from subprocess import call 

cmd = "scp [email protected]:files [email protected]:files" 
call(cmd.split(" ")) 
+1

Wie unterscheidet sich das wesentlich von dem vom Fragesteller erwähnten Basisfall? Ja, Subprozess ist besser als os.system, aber in beiden Fällen funktioniert es nicht außerhalb von Linux-ähnlichen Systemen, hat Probleme mit Passwortaufforderungen usw. – Foon