it-swarm-tr.com

SCP veya SSH kullanarak Python'daki bir uzak sunucuya dosya nasıl kopyalanır?

Yerel makinemde cron'da çalışan günlük bir Python betiği tarafından oluşturulan bir metin dosyasına sahibim. 

Bu dosyanın sunucuma SSH üzerinden güvenli bir şekilde gönderilmesini sağlamak için bir miktar kod eklemek istiyorum.

85
Alok

Basit bir yaklaşım istiyorsanız, bu çalışması gerekir.

İlk önce dosyayı ".close ()" yapmak isteyeceksiniz, böylece diskin Python'dan temizlendiğini bileceksiniz.

import os
os.system("scp FILE [email protected]:PATH")
#e.g. os.system("scp foo.bar [email protected]:/path/to/foo.bar")

Öncelikle bir ssh anahtarını (kaynak makinede) oluşturmanız ve (hedef makinede) bir ssh anahtarını önceden kurmanız gerekir; böylece scp otomatik olarak genel ssh anahtarınızla doğrulanır (başka bir deyişle, komut dosyanız bir şifre sormaz) . 

ssh-keygen örneği

39
pdq

Bunu Python'da yapmak (yani, scpro'yu subprocess.Popen veya benzeri ile sararmak değil) Paramiko library ile yapmak için, şöyle bir şey yapardınız:

import os
import paramiko

ssh = paramiko.SSHClient() 
ssh.load_Host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, password=password)
sftp = ssh.open_sftp()
sftp.put(localpath, remotepath)
sftp.close()
ssh.close()

(Muhtemelen bilinmeyen ana bilgisayarlar, hatalar, gerekli dizinleri oluşturma vb. İle uğraşmak istersiniz).

129
Tony Meyer

Muhtemelen subprocess module 'ı kullanırsınız. Bunun gibi bir şey:

import subprocess
p = subprocess.Popen(["scp", myfile, destination])
sts = os.waitpid(p.pid, 0)

Burada destination muhtemelen [email protected]:remotepath şeklindedir. @Charles Duffy, orijinal cevabımdaki zayıflığı işaret ettiğim için teşekkürler, bu da scp işlemini belirtmek için tek bir dize argümanı kullandı Shell=True - boşluklarda boşluk bırakmazdı.

Modül belgelerinde bu işlemle bağlantılı olarak gerçekleştirmek isteyebileceğiniz hata kontrolü örnekleri vardır.

Makineler arasında katılımsız, parolasız bir scp işlemi yapabilmeniz için uygun kimlik bilgileri ayarladığınızdan emin olun . Bunun için bir stackoverflow sorusu zaten var .

30
Blair Conrad

Soruna yaklaşmanın birkaç farklı yolu vardır:

  1. Komut satırı programlarını kaydır
  2. sSH yetenekleri sağlayan bir Python kütüphanesi kullanın (örn. - Paramiko veya Twisted Conch )

Her yaklaşımın kendine özgü tuhaflıkları vardır. Eğer "ssh", "scp" veya "rsync" gibi sistem komutlarını kullanıyorsanız, şifresiz girişleri etkinleştirmek için SSH anahtarlarını ayarlamanız gerekir. Paramiko veya başka bir kütüphane kullanarak bir betiğe şifre ekleyebilirsiniz, ancak özellikle SSH bağlantısının temellerini bilmiyorsanız (örneğin, anahtar değiş tokuşları, aracılar, vb.), Dokümantasyon eksikliğini bulabilirsiniz. Muhtemelen SSH anahtarlarının neredeyse her zaman bu tür şeyler için kullanılan parolalardan daha iyi bir fikir olduğunu söylemeye gerek yoktur.

NOT: SSH üzerinden dosya aktarmayı planlıyorsanız, özellikle alternatif düz eski scp ise rsync'i yenmek zor.

Paramiko'yu sistem çağrılarını değiştirmeye dönük bir gözle kullandım, ancak kullanım kolaylığı ve yakınlık durumları nedeniyle kendimi sarılı komutlara çekerken buldum. Farklı olabilirsin. Conch'a bir süre önce defalarca verdim ama bu bana çekici gelmedi.

Sistem çağrısı yolunu seçiyorsanız, Python os.system veya komutlar/alt işlem modülleri gibi bir dizi seçenek sunar. Sürüm 2.4+ kullanıyorsanız alt işlem modülü ile giderdim.

10
Michael

Aynı soruna ulaştım, ancak "hacklemek" veya öykünme komut satırı yerine:

Bu cevabı buldum burada .

from paramiko import SSHClient
from scp import SCPClient

ssh = SSHClient()
ssh.load_system_Host_keys()
ssh.connect('example.com')

with SCPClient(ssh.get_transport()) as scp:
    scp.put('test.txt', 'test2.txt')
    scp.get('test2.txt')
6
Maviles

Bunun gibi bir şey yapabilirsiniz, Ana bilgisayar tuşunu denetleme işlemini de yapmak için

import os
os.system("sshpass -p password scp -o StrictHostKeyChecking=no local_file_path [email protected]:remote_path")
4
Pradeep Pathak

fabric /, ssh ile dosya yüklemek için kullanılabilir:

#!/usr/bin/env python
from fabric.api import execute, put
from fabric.network import disconnect_all

if __name__=="__main__":
    import sys
    # specify hostname to connect to and the remote/local paths
    srcdir, remote_dirname, hostname = sys.argv[1:]
    try:
        s = execute(put, srcdir, remote_dirname, Host=hostname)
        print(repr(s))
    finally:
        disconnect_all()
3
jfs

Tam olarak bunun için tasarlanmış olan buhar paketini kullanabilirsiniz.

İhtiyacınız olan tek şey vassal yüklemek ve yapmak

from vassal.terminal import Terminal
Shell = Terminal(["scp [email protected]:/home/foo.txt foo_local.txt"])
Shell.run()

Ayrıca, kimlik bilgilerini doğrulamanızı sağlar ve tekrar tekrar yazmanız gerekmez.

1
Shawn
from paramiko import SSHClient
from scp import SCPClient
import os

ssh = SSHClient() 
ssh.load_Host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username='username', password='password')
with SCPClient(ssh.get_transport()) as scp:
        scp.put('test.txt', 'test2.txt')
0
michael

çok basit bir yaklaşım şudur: 

import os
os.system('sshpass -p "password" scp [email protected]:/path/to/file ./')

python kütüphanesi gerekmez (yalnızca işletim sistemi) ve çalışır

0

SSL sertifikalarını kullanmak istemiyorsanız bunu deneyin:

import subprocess

try:
    # Set scp and ssh data.
    connUser = 'john'
    connHost = 'my.Host.com'
    connPath = '/home/john/'
    connPrivateKey = '/home/user/myKey.pem'

    # Use scp to send file from local to Host.
    scp = subprocess.Popen(['scp', '-i', connPrivateKey, 'myFile.txt', '{}@{}:{}'.format(connUser, connHost, connPath)])

except CalledProcessError:
    print('ERROR: Connection to Host failed!')
0
JavDomGom

Uzak dizini ssh ile bağlamak için sshfs ve dosyaları kopyalamak için shutil kullandım:

$ mkdir ~/sshmount
$ sshfs [email protected]:/path/to/remote/dst ~/sshmount

Sonra python içinde:

import shutil
shutil.copy('a.txt', '~/sshmount')

Bu yöntem, yerel olarak önbelleğe almak ve tek bir büyük dosyayı göndermek yerine veri oluşturuyorsanız veri akışı sağlayabileceğiniz avantajına sahiptir.

0
Jonno_FTW

Alt işlem aracılığıyla scp komutunu çağırmak, komut dosyasındaki ilerleme raporunun alınmasına izin vermez. pexpect bu bilgiyi çıkarmak için kullanılabilir:

import pipes
import re
import pexpect # $ pip install pexpect

def progress(locals):
    # extract percents
    print(int(re.search(br'(\d+)%$', locals['child'].after).group(1)))

command = "scp %s %s" % Tuple(map(pipes.quote, [srcfile, destination]))
pexpect.run(command, events={r'\d+%': progress})

Yerel ağda python kopya dosyasına bakın (linux -> linux)

0
jfs