SFTP ใน Python? (แพลตฟอร์มอิสระ)


181

ฉันกำลังทำงานกับเครื่องมือง่ายๆที่ถ่ายโอนไฟล์ไปยังตำแหน่งที่กำหนดรหัสผ่านด้วยรหัสผ่านและรหัสตายตัว ฉันเป็นงูหลามสามเณร แต่ต้องขอบคุณ 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 วิธีปกติในการทำสิ่งนี้อย่างปลอดภัยคืออะไร

แก้ไข: ขอบคุณคำตอบที่นี่ฉันได้รับมันทำงานร่วมกับ 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.'

ขอบคุณอีกครั้ง!


1
ขอบคุณมาก! มีสคริปต์การอัปโหลด SFTP ทำงานใน 5 นาที :)
Ohad Schneider

1
เพียงแค่ทราบทั่วไปเกี่ยวกับคำถามเดิมว่างูหลาม ftplib ยังมีการสนับสนุน FTPS - FTP ผ่าน TLS en.m.wikipedia.org/wiki/FTPS เซิร์ฟเวอร์ FTPS นั้นมีการใช้งานน้อยกว่าในโลก Unix ส่วนหนึ่งเป็นผลมาจากการใช้งาน ssh / sftp อย่างไรก็ตามเซิร์ฟเวอร์ sftp นั้นมีอยู่น้อยกว่ามากในสภาพแวดล้อมของ Windows ซึ่ง FTPS เป็นเรื่องธรรมดา
Gnudiff

ดูเหมือนว่ามีการเพิ่มการสนับสนุน FTPS ใน Python 3.2 พร้อมกับเพิ่มคลาสแหล่งที่มา : class ftplib.FTP_TLS (host = '', user = '', passwd = '', acct = '', keyfile = ไม่มี, certfile = ไม่มี, บริบท = ไม่มี, หมดเวลา = ไม่มี, source_address = ไม่มี)
mgrollins

คำตอบ:


109

Paramikoรองรับ SFTP ฉันใช้แล้วและฉันใช้ Twisted ทั้งคู่มีสถานที่ของพวกเขา แต่คุณอาจพบว่าการเริ่มต้นกับ Paramiko ง่ายขึ้น


2
yepp, paramiko เป็นวิธีที่จะไป (ใช้งานง่ายสุด ๆ ) มันค่อนข้างยุ่งยากในการค้นหาแพ็คเกจ windows ของ pycrypto ซึ่งเป็นที่พึ่ง
mauli

ขอบคุณ. ฉันใช้เวลาสักครู่ในการหาวิธีการติดตั้งแพคเกจเนื่องจากการขาดคำแนะนำในการติดตั้งใน readme แต่มันเป็นสิ่งที่ฉันต้องการ!
Mark Wilbur

15
ดูbitprophet.org/blog/2012/09/29/paramiko-and-sshซึ่ง Jeff Forcier อธิบายว่า ssh ล้าสมัยและ paramiko เป็นหนทางข้างหน้า
Christopher Mahan

2
นอกจากนี้ยังมีcode.google.com/p/pysftpซึ่งมีพื้นฐานจาก Paramiko แต่ใช้ง่ายกว่า
franzlorenzon


78

คุณควรตรวจสอบ 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.'

4
โหวตwithในตัวอย่าง
Roman Podlinov

2
pip install pysftp
Bob Stein

2
มีตัวเลือกให้เพิ่มโฮสต์ sftp ใหม่ไปยังโฮสต์ที่รู้จักโดยอัตโนมัติหรือไม่?
user443854

1
@ user443854 ใช่มีpysftp.readthedocs.io/en/release_0.2.9/แต่ฉันจะไม่แนะนำอย่างแน่นอนถึงแม้ว่าคุณสามารถเพิ่มไฟล์ known_host อีกไฟล์
AsTeR

15

ถ้าคุณต้องการง่ายและเรียบง่ายคุณอาจต้องการดูผ้าเนื้อผ้ามันเป็นเครื่องมือปรับใช้แบบอัตโนมัติเช่น Capy'sano ของรูบี้ แต่ง่ายกว่าและแน่นอนสำหรับ Python มันสร้างจากบน Paramiko

คุณอาจไม่ต้องการ 'ปรับใช้อัตโนมัติ' แต่ผ้าจะเหมาะกับกรณีการใช้งานของคุณอย่างสมบูรณ์แบบไม่น้อย เพื่อแสดงให้คุณเห็นว่า 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

และคุณทำเสร็จแล้ว! :)


12

นี่คือตัวอย่างการใช้ 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 connection

pysftp เป็นโมดูล 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 ที่นี่


srv.get(file_path) # Download a file from remote serverคุณสามารถอธิบายที่ไม่ได้ดาวน์โหลดไฟล์ลง?
Markus Meskanen

คุณลองท้องถิ่นที่คุณดำเนินการมาหรือไม่
radtek

ใช่ แต่อยู่ที่ไหนในระบบไฟล์? ทุกอย่างประสบความสำเร็จ แต่ฉันไม่สามารถค้นหาไฟล์ได้จากทุกที่
Markus Meskanen

ขอโทษฉันหมายถึงผบ. ลองเรียกใช้สคริปต์จาก dir ที่บ้านของคุณและดูว่ามีไฟล์อยู่หรือไม่
radtek

3

Twistedสามารถช่วยคุณในสิ่งที่คุณทำตรวจสอบเอกสารประกอบของพวกเขามีตัวอย่างมากมาย นอกจากนี้ยังเป็นผลิตภัณฑ์สำหรับผู้ใหญ่ที่มีชุมชนผู้พัฒนา / ผู้ใช้รายใหญ่อยู่ข้างหลัง



1

ด้วยรหัส 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)

0

มีคำตอบมากมายที่พูดถึง pysftp ดังนั้นในกรณีที่คุณต้องการ wrapper บริบทจัดการรอบ ๆ pysftp ต่อไปนี้เป็นวิธีแก้ปัญหาที่แม้แต่โค้ดน้อยลงซึ่งดูเหมือนว่าต่อไปนี้เมื่อใช้

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

ตัวอย่าง (ฟุลเลอร์): http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html

ตัวจัดการบริบทนี้มีตรรกะการลองอัตโนมัติซ้ำอีกครั้งในกรณีที่คุณไม่สามารถเชื่อมต่อเป็นครั้งแรก (ซึ่งเกิดขึ้นอย่างน่าประหลาดใจบ่อยกว่าที่คุณคาดหวังในสภาพแวดล้อมการผลิต ... )

ตัวจัดการบริบทประกอบด้วยopen_sftp: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515


0

ปารามิโกช้ามาก ใช้กระบวนการย่อยและเชลล์นี่คือตัวอย่าง:

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)

คำถามเกี่ยวกับ "Python" ซึ่งโดยทั่วไปหมายถึงการเกาะติดอยู่ภายใน - โดยเฉพาะเมื่อมีตัวเลือกมากมายสำหรับการทำเช่นนั้น ที่สำคัญกว่านั้นมันบอกว่า "แพลตฟอร์มอิสระ" ฉันไม่สามารถพูดได้ว่าคำตอบของคุณทำงานเร็วขึ้นหรือไม่ บางที?
BuvinJ

0

PyFilesystemพร้อมsshfsเป็นทางเลือกหนึ่ง มันใช้ Paramiko ภายใต้ประทุนและให้อินเทอร์เฟซอิสระ nicer paltform ด้านบน

import fs

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

หรือ

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

-1

คุณสามารถใช้โมดูล pexpect

นี่คือโพสต์บทนำที่ดี

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

ฉันยังไม่ได้ทดสอบสิ่งนี้ แต่ควรใช้งานได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.