SFTP dengan Python? (platform independen)


181

Saya sedang mengerjakan alat sederhana yang mentransfer file ke lokasi yang dikodekan dengan kata sandi juga yang dikodekan. Saya seorang pemula python, tetapi berkat ftplib, itu mudah:

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)

Masalahnya adalah saya tidak dapat menemukan perpustakaan yang mendukung sFTP. Apa cara normal untuk melakukan hal seperti ini dengan aman?

Sunting: Berkat jawaban di sini, saya sudah bisa bekerja dengan Paramiko dan ini adalah sintaksnya.

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

Terima kasih lagi!


1
Terima kasih! Dapatkan skrip unggah SFTP bekerja dalam 5 menit :)
Ohad Schneider

1
Hanya sebuah catatan umum tentang pertanyaan awal bahwa python ftplib juga mendukung FTPS - ftp over TLS en.m.wikipedia.org/wiki/FTPS . Server FTPS bisa dibilang lebih sedikit digunakan di dunia Unix, sebagian karena omnipresence dari ssh / sftp, namun, server sftp jauh lebih sedikit hadir di lingkungan Windows, di mana FTPS lebih umum.
Gnudiff

Sepertinya dukungan FTPS ditambahkan dalam Python 3.2 dengan sumber kelas yang diperluas : class ftplib.FTP_TLS (host = '', user = '', passwd = '', acct = '', keyfile = Tidak ada, certfile = Tidak ada, certfile = Tidak ada, konteks = Tidak ada, batas waktu = Tidak ada, source_address = Tidak ada)
mgrollin

Jawaban:


109

Paramiko mendukung SFTP. Saya sudah menggunakannya, dan saya sudah menggunakan Twisted. Keduanya memiliki tempat masing-masing, tetapi Anda mungkin merasa lebih mudah untuk memulai dengan Paramiko.


2
ya, paramiko adalah cara untuk pergi (super mudah digunakan), ini agak sulit untuk menemukan paket windows dari pycrypto yang merupakan ketergantungan.
Mauli

Terima kasih. Butuh beberapa saat untuk mencari tahu cara menginstal paket karena kurangnya instruksi instalasi di readme tapi itu persis apa yang saya butuhkan!
Mark Wilbur

15
Lihat bitprophet.org/blog/2012/09/29/paramiko-and-ssh di mana Jeff Forcier menjelaskan bahwa ssh sudah usang dan paramiko adalah jalan ke depan.
Christopher Mahan

2
Ada juga code.google.com/p/pysftp yang didasarkan pada Paramiko, tetapi lebih mudah digunakan
franzlorenzon


78

Anda harus memeriksa pysftp https://pypi.python.org/pypi/pysftp itu tergantung pada paramiko, tetapi membungkus kasus penggunaan yang paling umum menjadi hanya beberapa baris kode.

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
Pilih withdalam contoh
Roman Podlinov

2
pip install pysftp
Bob Stein

2
Apakah ada opsi untuk secara otomatis menambahkan host sftp baru ke host yang dikenal?
user443854

1
@ user443854 ya ada pysftp.readthedocs.io/en/release_0.2.9/… Tapi saya pasti tidak akan merekomendasikan itu, meskipun Anda dapat menambahkan file
diketahui_host

15

Jika Anda ingin mudah dan sederhana, Anda mungkin juga ingin melihat Fabric . Ini adalah alat penyebaran otomatis seperti Capistrano Ruby, tetapi lebih sederhana dan tentu saja untuk Python. Itu dibangun di atas Paramiko.

Anda mungkin tidak ingin melakukan 'penyebaran otomatis' tetapi Fabric akan cocok dengan kasus penggunaan Anda dengan sempurna. Untuk menunjukkan kepada Anda betapa mudahnya Fabric adalah: file dan perintah fab untuk skrip Anda akan terlihat seperti ini (tidak diuji, tetapi 99% yakin itu akan berhasil):

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

Kemudian jalankan file dengan perintah fab:

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

Dan kamu selesai! :)


12

Berikut adalah contoh menggunakan pysftp dan kunci pribadi.

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 adalah modul sftp yang mudah digunakan yang memanfaatkan paramiko dan pycrypto. Ini menyediakan antarmuka sederhana untuk sftp .. Hal-hal lain yang dapat Anda lakukan dengan pysftp yang sangat berguna:

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

Lebih banyak perintah dan tentang PySFTP di sini .


srv.get(file_path) # Download a file from remote serverdapatkah Anda menjelaskan di mana file tersebut diunduh?
Markus Meskanen

Apakah Anda mencoba lokal untuk Anda dieksekusi?
radtek

Ya tapi di mana pada sistem file? Semuanya berjalan dengan sukses tetapi saya tidak dapat menemukan file dari mana pun.
Markus Meskanen

Maaf saya maksud dir lokal. Coba jalankan skrip dari direktori home Anda dan lihat apakah file ada di sana.
radtek


1

Dengan RSA Key, lalu rujuk di sini

Potongan:

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

Ada banyak jawaban yang menyebutkan pysftp, jadi jika Anda menginginkan pembungkus manajer konteks di sekitar pysftp, berikut adalah solusi yang lebih sedikit kode yang akhirnya tampak seperti berikut ketika digunakan

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

Contoh (lebih lengkap): http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html

Manajer konteks ini kebetulan memiliki logika coba ulang otomatis jika Anda tidak dapat terhubung pertama kali (yang secara mengejutkan terjadi lebih sering daripada yang Anda harapkan dalam lingkungan produksi ...)

Inti manajer konteks untuk open_sftp: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515


0

Paramiko sangat lambat. Gunakan subproses dan shell, berikut adalah contohnya:

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)

Pertanyaannya adalah tentang "Python", yang umumnya menyiratkan menempel di dalamnya - terutama ketika ada begitu banyak pilihan untuk melakukannya. Lebih penting lagi, ia mengatakan "Platform independen". Saya tidak bisa mengatakan apakah jawaban Anda bekerja lebih cepat atau tidak. Mungkin?
BuvinJ

0

Sistem PyFiles dengan sshfs adalah salah satu opsi. Ini menggunakan Paramiko di bawah tenda dan menyediakan antarmuka independen paltform lebih bagus di atas.

import fs

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

atau

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

-1

Anda dapat menggunakan modul pexpect

Ini adalah posting intro yang bagus

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

Saya belum menguji ini tetapi harus berhasil

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.