SFTP trong Python? (nền tảng độc lập)


181

Tôi đang làm việc trên một công cụ đơn giản để chuyển các tệp đến một vị trí được mã hóa cứng với mật khẩu cũng được mã hóa cứng. Tôi là một người mới làm trăn, nhưng nhờ có ftplib, thật dễ dàng:

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)

Vấn đề là tôi không thể tìm thấy bất kỳ thư viện nào hỗ trợ sFTP. Cách bình thường để làm một cái gì đó như thế này một cách an toàn là gì?

Chỉnh sửa: Nhờ các câu trả lời ở đây, tôi đã làm cho nó hoạt động với Paramiko và đây là cú pháp.

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.'

Cảm ơn một lần nữa!


1
Cảm ơn ! Có một kịch bản tải lên SFTP hoạt động trong 5 phút :)
Ohad Schneider

1
Chỉ cần một lưu ý chung về câu hỏi ban đầu là python ftplib cũng đã hỗ trợ FTPS - ftp trên TLS en.m.wikipedia.org/wiki/FTPS . Các máy chủ FTPS được cho là ít được sử dụng trong thế giới Unix, một phần do sự toàn năng của ssh / sftp, tuy nhiên, các máy chủ sftp ít hiện diện hơn trong môi trường Windows, nơi FTPS phổ biến hơn.
Gnudiff

Có vẻ như hỗ trợ FTPS đã được thêm vào Python 3.2 với nguồn lớp mở rộng : class ftplib.FTP_TLS (host = '', user = '', passwd = '', acct = '', keyfile = none, certfile = none, bối cảnh = Không có, thời gian chờ = Không có, source_address = Không)
mgrollins

Câu trả lời:


109

Paramiko hỗ trợ SFTP. Tôi đã sử dụng nó và tôi đã sử dụng Twisted. Cả hai đều có vị trí của chúng, nhưng bạn có thể thấy dễ dàng hơn khi bắt đầu với Paramiko.


2
yepp, paramiko là cách để đi (siêu dễ sử dụng), hơi khó để tìm gói windows của pycrypto vốn là một phụ thuộc.
Mauli

Cảm ơn bạn. Tôi phải mất một thời gian để tìm ra cách cài đặt gói do thiếu hướng dẫn cài đặt trong readme nhưng đó chính xác là những gì tôi cần!
Đánh dấu Wilbur

15
Xem bitprophet.org/blog/2012/09/29/paramiko-and-ssh trong đó Jeff Forcier giải thích rằng ssh đã lỗi thời và paramiko là con đường phía trước.
Christopher Mahan

2
Ngoài ra còn có code.google.com/p/pysftp dựa trên Paramiko, nhưng dễ sử dụng hơn
franzlorenzon


78

Bạn nên kiểm tra pysftp https://pypi.python.org/pypi/pysftp, nó phụ thuộc vào paramiko, nhưng bao bọc hầu hết các trường hợp sử dụng phổ biến cho chỉ một vài dòng mã.

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.'

4
Bỏ phiếu cho withví dụ
Roman Podlinov

2
pip install pysftp
Bob Stein

2
Có một tùy chọn để tự động thêm máy chủ sftp mới vào các máy chủ đã biết không?
dùng443854

1
@ user443854 vâng, có pysftp.readthedocs.io/en/release_0.2.9/ Nhưng Nhưng tôi chắc chắn sẽ không khuyến nghị điều đó, mặc dù bạn có thể thêm một tệp
know_host khác

15

Nếu bạn muốn dễ dàng và đơn giản, bạn cũng có thể muốn xem Fabric . Đây là một công cụ triển khai tự động như Capistrano của Ruby, nhưng đơn giản hơn và tất nhiên là dành cho Python. Nó được xây dựng trên đỉnh Paramiko.

Bạn có thể không muốn thực hiện 'triển khai tự động' nhưng Fabric sẽ hoàn toàn phù hợp với trường hợp sử dụng của bạn. Để cho bạn thấy Fabric đơn giản như thế nào: tệp fab và lệnh cho tập lệnh của bạn sẽ trông như thế này (không được kiểm tra, nhưng chắc chắn 99% nó sẽ hoạt động):

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

Sau đó chạy tệp bằng lệnh fab:

fab -f fab_putfile.py put_file:file=./path/to/my/file

Và bạn đã hoàn thành! :)


12

Đây là một mẫu sử dụng pysftp và khóa riêng.

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 là một mô-đun sftp dễ sử dụng sử dụng paramiko và pycrypto. Nó cung cấp một giao diện đơn giản cho sftp .. Những thứ khác mà bạn có thể làm với pysftp khá hữu ích:

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

Thêm lệnh và về PySFTP ở đây .


srv.get(file_path) # Download a file from remote serverbạn có thể giải thích nơi nào nó tải file vào?
Markus Meskanen

Bạn đã thử địa phương cho bạn thực hiện từ?
radtek

Vâng, nhưng ở đâu trên hệ thống tập tin? Mọi thứ đều diễn ra thành công nhưng dường như tôi không thể tìm thấy tập tin từ bất cứ đâu.
Markus Meskanen

Xin lỗi tôi có nghĩa là dir địa phương. Hãy thử thực thi tập lệnh từ thư mục nhà của bạn và xem nếu tập tin ở đó.
radtek

3

Twisted có thể giúp bạn với những gì bạn đang làm, kiểm tra tài liệu của họ, có rất nhiều ví dụ. Ngoài ra, nó là một sản phẩm trưởng thành với một cộng đồng nhà phát triển / người dùng lớn đằng sau nó.



1

Với khóa RSA thì tham khảo tại đây

Đoạn trích:

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)

0

Có một loạt các câu trả lời đề cập đến pysftp, vì vậy trong trường hợp bạn muốn có một trình bao bọc trình quản lý bối cảnh xung quanh pysftp, đây là một giải pháp thậm chí ít mã hơn mà cuối cùng trông giống như sau khi được sử dụng

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.") 

Ví dụ (đầy đủ hơn): http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html

Trình quản lý bối cảnh này tình cờ có logic tự động thử lại trong trường hợp bạn không thể kết nối lần đầu tiên (điều đáng ngạc nhiên xảy ra thường xuyên hơn bạn mong đợi trong môi trường sản xuất ...)

Trình quản lý bối cảnh cho open_sftp: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515


0

Paramiko rất chậm. Sử dụng quy trình con và shell, đây là một ví dụ:

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)

Câu hỏi là về "Python", thường ngụ ý gắn bó trong đó - đặc biệt là khi có rất nhiều lựa chọn để làm như vậy. Quan trọng hơn, nó nói "Nền tảng độc lập". Tôi không thể nói nếu câu trả lời của bạn hoạt động nhanh hơn hay không. Có lẽ?
BuvinJ

0

PyFilesystem với sshfs của nó là một tùy chọn. Nó sử dụng Paramiko dưới mui xe và cung cấp một giao diện độc lập paltform đẹp hơn trên đầu.

import fs

sf = fs.open_fs("sftp://[user[:password]@]host[:port]/[directory]")
sf.makedir('my_dir')

hoặc là

from fs.sshfs import SSHFS
sf = SSHFS(...

-1

Bạn có thể sử dụng mô-đun khai thác

Đây là một bài giới thiệu tốt

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')

Tôi đã không thử nghiệm điều này nhưng nó sẽ hoạt động

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.