SFTP in Python? (Piattaforma indipendente)
Domanda
Sto lavorando a un semplice strumento che trasferisce i file in una posizione codificata con la password anch'essa codificata. Sono un principiante di Python, ma grazie a ftplib è stato facile:
import ftplib
info= ('someuser', 'password') #hard-coded
def putfile(file, site, dir, user=(), verbose=True):
"""
upload a file by ftp to a site/directory
login hard-coded, binary transfer
"""
if verbose: print 'Uploading', file
local = open(file, 'rb')
remote = ftplib.FTP(site)
remote.login(*user)
remote.cwd(dir)
remote.storbinary('STOR ' + file, local, 1024)
remote.quit()
local.close()
if verbose: print 'Upload done.'
if __name__ == '__main__':
site = 'somewhere.com' #hard-coded
dir = './uploads/' #hard-coded
import sys, getpass
putfile(sys.argv[1], site, dir, user=info)
Il problema è che non riesco a trovare alcuna libreria che supporti sFTP. Qual è il modo normale di fare qualcosa di simile in modo sicuro?
Modifica: grazie alle risposte qui, l'ho fatto funzionare con Paramiko e questa era la sintassi.
import paramiko
host = "THEHOST.com" #hard-coded
port = 22
transport = paramiko.Transport((host, port))
password = "THEPASSWORD" #hard-coded
username = "THEUSERNAME" #hard-coded
transport.connect(username = username, password = password)
sftp = paramiko.SFTPClient.from_transport(transport)
import sys
path = './THETARGETDIRECTORY/' + sys.argv[1] #hard-coded
localpath = sys.argv[1]
sftp.put(localpath, path)
sftp.close()
transport.close()
print 'Upload done.'
Grazie ancora!
Soluzione
Paramiko supporta SFTP. L'ho usato e ho usato Twisted. Entrambi hanno il loro posto, ma potresti trovare più facile iniziare con Paramiko.
Altri suggerimenti
Dovresti dare un'occhiata a pysftp https://pypi.python.org/pypi/pysftp dipende da paramiko, ma racchiude i casi d'uso più comuni in poche righe di codice.
import pysftp
import sys
path = './THETARGETDIRECTORY/' + sys.argv[1] #hard-coded
localpath = sys.argv[1]
host = "THEHOST.com" #hard-coded
password = "THEPASSWORD" #hard-coded
username = "THEUSERNAME" #hard-coded
with pysftp.Connection(host, username=username, password=password) as sftp:
sftp.put(localpath, path)
print 'Upload done.'
Se vuoi essere facile e semplice, potresti anche voler guardare Fabric . È uno strumento di distribuzione automatizzato come Ruby Capistrano, ma più semplice e ovviamente per Python. È basato su Paramiko.
Potresti non voler fare una 'distribuzione automatizzata' ma Fabric si adatterà perfettamente al tuo caso d'uso comunque. Per mostrarti quanto è semplice Fabric: il file e il comando fab per il tuo script sarebbero così (non testati, ma sicuro al 99% funzionerà):
fab_putfile.py:
from fabric.api import *
env.hosts = ['THEHOST.com']
env.user = 'THEUSER'
env.password = 'THEPASSWORD'
def put_file(file):
put(file, './THETARGETDIRECTORY/') # it's copied into the target directory
Quindi eseguire il file con il comando fab:
fab -f fab_putfile.py put_file:file=./path/to/my/file
E il gioco è fatto! :)
Ecco un esempio che utilizza pysftp e una chiave privata.
import pysftp
def upload_file(file_path):
private_key = "~/.ssh/your-key.pem" # can use password keyword in Connection instead
srv = pysftp.Connection(host="your-host", username="user-name", private_key=private_key)
srv.chdir('/var/web/public_files/media/uploads') # change directory on remote server
srv.put(file_path) # To download a file, replace put with get
srv.close() # Close connection
pysftp è un modulo sftp facile da usare che utilizza paramiko e pycrypto. Fornisce una semplice interfaccia per sftp .. Altre cose che puoi fare con pysftp che sono abbastanza utili:
data = srv.listdir() # Get the directory and file listing in a list
srv.get(file_path) # Download a file from remote server
srv.execute('pwd') # Execute a command on the server
Altri comandi e informazioni su PySFTP qui .
Twisted può aiutarti in quello che stai facendo, controlla la loro documentazione, ci sono molti esempi . Inoltre è un prodotto maturo con dietro una grande comunità di sviluppatori / utenti.
Puoi utilizzare il modulo pexpect
Ecco una buona introduzione pubblicare
child = pexpect.spawn ('/usr/bin/sftp ' + user@ftp.site.com )
child.expect ('.* password:')
child.sendline (your_password)
child.expect ('sftp> ')
child.sendline ('dir')
child.expect ('sftp> ')
file_list = child.before
child.sendline ('bye')
Non l'ho provato ma dovrebbe funzionare
Paramiko è così lento. Usa sottoprocesso e shell, ecco un esempio:
remote_file_name = "filename"
remotedir = "/remote/dir"
localpath = "/local/file/dir"
ftp_cmd_p = """
#!/bin/sh
lftp -u username,password sftp://ip:port <<EOF
cd {remotedir}
lcd {localpath}
get {filename}
EOF
"""
subprocess.call(ftp_cmd_p.format(remotedir=remotedir,
localpath=localpath,
filename=remote_file_name
),
shell=True, stdout=sys.stdout, stderr=sys.stderr)
Con RSA Key quindi fai riferimento a qui
Snippet:
import pysftp
import paramiko
from base64 import decodebytes
keydata = b"""L+WsiL5VL51ecJi3LVjmblkAdUTU+xbmXmUArIU5+8N6ua76jO/+T"""
key = paramiko.RSAKey(data=decodebytes(keydata))
cnopts = pysftp.CnOpts()
cnopts.hostkeys.add(host, 'ssh-rsa', key)
with pysftp.Connection(host=host, username=username, password=password, cnopts=cnopts) as sftp:
with sftp.cd(directory):
sftp.put(file_to_sent_to_ftp)
Ci sono un sacco di risposte che menzionano pysftp, quindi nel caso in cui si desideri un wrapper del gestore di contesto attorno a pysftp, ecco una soluzione che è ancora meno codice che finisce per apparire come il seguente quando usato
path = "sftp://user:p@ssw0rd@test.com/path/to/file.txt"
# Read a file
with open_sftp(path) as f:
s = f.read()
print s
# Write to a file
with open_sftp(path, mode='w') as f:
f.write("Some content.")
L'esempio (più completo): http: / /www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html
Questo gestore di contesto ha una logica di ripetizione automatica inserita nel caso in cui non sia possibile connettersi per la prima volta (cosa che accade sorprendentemente più spesso di quanto ci si aspetterebbe in un ambiente di produzione ...)
Il gestore del contesto per open_sftp
: https: //gist.github .com / prschmid / 80a19c22012e42d4d6e791c1e4eb8515