SFTP em Python? (plataforma independente)
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)
o problema é que não consigo encontrar nenhuma biblioteca que suporte o sFTP. Qual é a maneira normal de fazer algo assim de forma segura?
[[3]}Edit: graças às respostas aqui, eu consegui trabalhar com Paramiko e esta foi a sintaxe.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.'
Obrigado mais uma vez!
9 answers
Paramiko suporta o SFTP. Eu usei-o, e usei o Twisted. Ambos têm o seu lugar, mas talvez seja mais fácil começar com a Paramiko.
Devias ver o pysftp https://pypi.python.org/pypi/pysftp depende de paramiko, mas envolve os casos de uso mais comuns a apenas algumas linhas de código.
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 você quer fácil e simples, você também pode querer olhar paraTecido . É uma ferramenta de implantação automatizada como o Capistrano de Ruby, mas mais simples e ofc ourse para Python. É construído em cima da Paramiko.
Pode não querer fazer "implantação automatizada", mas o tecido adequava-se perfeitamente à sua mala de uso. Para lhe mostrar o quão simples é o tecido: o ficheiro fab e o comando para o seu programa ficaria assim (não testado, mas 99% de certeza que irá trabalho):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
Depois execute o ficheiro com o comando fab:
fab -f fab_putfile.py put_file:file=./path/to/my/file
E acabou-se! :)
Aqui está uma amostra usando o pysftp e uma chave privada.
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 é um módulo sftp fácil de usar que utiliza paramiko e pycrypto. Ele fornece uma interface simples para sftp.. Outras coisas que você pode fazer com o pysftp que são bastante úteis:
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
Mais Comandos e sobre o PySFTP aqui.
Twisted pode ajudá-lo com o que está a fazer, Verifique a documentação deles, existem muitos exemplos. Também é um produto maduro com uma grande comunidade de desenvolvedores/usuários por trás dele.
Pode usar o Módulo pexpect
Aqui está um bom post de Introdução
child = pexpect.spawn ('/usr/bin/sftp ' + [email protected] )
child.expect ('.* password:')
child.sendline (your_password)
child.expect ('sftp> ')
child.sendline ('dir')
child.expect ('sftp> ')
file_list = child.before
child.sendline ('bye')
Ainda não testei isto, mas deve funcionar.
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)
Com a chave RSA, consulte então aqui
Excerto:
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)
Há um monte de respostas que mencionam o pysftp, por isso, no caso de você querer um pacote de Gerenciador de contexto em torno do pysftp, aqui está uma solução que é ainda menos código que acaba parecendo o seguinte quando usado
path = "sftp://user:p@[email protected]/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.")
O exemplo (mais completo): http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html
Acontece que este gestor de contexto tem a lógica de auto-repetição cozida no caso de não se conseguir ligar pela primeira vez (o que surpreendentemente acontece mais vezes do que seria de esperar num ambiente de produção...)O Gestor de contexto gist para open_sftp
: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515