SFTP в Python? (платформо-независимый)
Я работаю над простым инструментом, который передает файлы в жестко закодированное место с паролем, также жестко закодированным. Я новичок в питоне, но благодаря ftplib, это было легко:
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)
Проблема в том, что я не могу найти ни одной библиотеки, поддерживающей sFTP. Каков нормальный способ сделать что-то подобное безопасно?
Edit: благодаря ответам здесь, я получил его, работая с Paramiko, и это был синтаксис.
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.'
Еще раз спасибо!
9 ответов:
Paramiko поддерживает SFTP. Я использовал его,и я использовал Twisted. У обоих есть свое место, но вам, возможно, будет легче начать с Парамико.
Вы должны проверить pysftp https://pypi.python.org/pypi/pysftp это зависит от paramiko, но обертывает наиболее распространенные случаи использования всего в несколько строк кода.
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.'
Если вы хотите легко и просто, вы можете также посмотреть на ткань. Это автоматизированный инструмент развертывания, подобный Ruby's Capistrano, но более простой и ofc ourse для Python. Он построен на вершине Парамико.
Возможно, вы не захотите делать "автоматическое развертывание", но Fabric идеально подойдет для вашего варианта использования. Чтобы показать вам, насколько проста ткань: файл fab и команда для вашего скрипта будут выглядеть так (не протестированы, но на 99% уверены, что это будет работа):
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Затем запустите файл с помощью команды fab:
fab -f fab_putfile.py put_file:file=./path/to/my/fileИ вы закончили! :)
Вот пример использования pysftp и закрытого ключа.
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 connectionPysftp-это простой в использовании sftp-модуль, который использует paramiko и pycrypto. Он предоставляет простой интерфейс для sftp.. Другие вещи, которые вы можете сделать с pysftp, которые весьма полезны:
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Больше команд и о PySFTP здесь .
Twisted может помочь вам в том, что вы делаете, проверьте их документацию, есть много примеров. Кроме того, это зрелый продукт, за которым стоит большое сообщество разработчиков/пользователей.
Вы можете использовать модуль pexpect
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')Я не проверял это, но это должно работать
Парамико такая медлительная. Используйте подпроцесс и оболочку, вот пример:
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)
С ключом RSA затем обратитесь сюда
Фрагмент:
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)
Есть куча ответов, которые упоминают pysftp, поэтому в том случае, если вам нужна оболочка context manager вокруг pysftp, вот решение, которое еще меньше кода, который в конечном итоге выглядит следующим образом при использовании
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.")Более полный пример: http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html
Этот контекстный менеджер имеет логику автоматического повтора, запеченную в случае, если вы не можете подключиться в первый раз (что удивительно происходит чаще, чем можно было бы ожидать в производственной среде...)
Суть контекстного менеджера для
open_sftp: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515
Comments