Python'da scp nasıl?


158

Python'da bir dosyayı scp etmenin en pythonic yolu nedir? Fark ettiğim tek rota

os.system('scp "%s" "%s:%s"' % (localfile, remotehost, remotefile) )

ki bu bir hack'tir ve Linux benzeri sistemlerin dışında çalışmaz ve uzak ana bilgisayara önceden şifresiz SSH ayarlanmamışsa şifre istemlerinden kaçınmak için Pexpect modülünden yardıma ihtiyaç duyar.

Twisted'in farkındayım conch, ancak scp'yi düşük seviyeli ssh modülleriyle uygulamaktan kaçınmayı tercih ederim.

paramikoSSH ve SFTP'yi destekleyen bir Python modülü olduğunun farkındayım ; ancak SCP'yi desteklemez.

Arka plan: SFTP'yi desteklemeyen ancak SSH / SCP'yi destekleyen bir yönlendiriciye bağlanıyorum, bu nedenle SFTP bir seçenek değil.

EDIT : Bu bir dosyayı SCP veya SSH kullanarak Python uzak bir sunucuya kopyalamak nasıl? . Ancak , bu soru Python içindeki anahtarlarla ilgilenen scp'ye özel bir cevap vermez. Ben kod tür çalıştırmak için bir yol umuyorum

import scp

client = scp.Client(host=host, user=user, keyfile=keyfile)
# or
client = scp.Client(host=host, user=user)
client.use_system_keys()
# or
client = scp.Client(host=host, user=user, password=password)

# and then
client.transfer('/etc/local/filename', '/etc/remote/filename')

Yanıtlar:


107

Paramiko için Python scp modülünü deneyin . Kullanımı çok kolay. Aşağıdaki örneğe bakın:

import paramiko
from scp import SCPClient

def createSSHClient(server, port, user, password):
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(server, port, user, password)
    return client

ssh = createSSHClient(server, port, user, password)
scp = SCPClient(ssh.get_transport())

Sonra SCP işlemlerini yapmak için scp.get()veya öğesini arayın scp.put().

( SCPClient kodu )


3
Bu modül aslında paramiko kullanmıyorsa - sonunda sadece * nix üzerinde çalışan komut satırını scpçağıran bir sürü kod var scp.
Nick Bastin

8
Kabul, ne kaynak kodunda görüyorsanız uzak için çağrıdır scp -tveya scp -f(bu sunucu tarafı amaç için mevcut modları, 'dan' 'to' ve). Bu aslında scp nasıl çalışır - sunucuda mevcut scp başka bir kopyasına dayanır. Bu makale çok iyi açıklıyor: blogs.oracle.com/janp/entry/how_the_scp_protocol_works
laher

8
Bu çözüm benim için iki uyarı ile çalıştı: 1. Bunlar benim kullandığım ithalat ifadeleri: import paramiko from scp import SCPClient2. İşte scp.get () komutunun bir örneği:scp.get(r'/nfs_home/appers/xxxx/test2.txt', r'C:\Users\xxxx\Desktop\MR_Test')
Chris Nielsen

Bu sadece harika değil, aynı zamanda varsa SSH anahtarlarından da yararlanır.
Marcel Wilson

Bu lib'i PyPI'den de kurabileceğinizi unutmayın:, pip install scpbu yazıdan itibaren 0.10.2 sürümünde.
Andrew

15

Pexpect'i ( kaynak kodu ) denemek isteyebilirsiniz . Bu, şifreniz için etkileşimli istemlerle başa çıkmanızı sağlar.

Ana web sitesinden örnek kullanım (snp için) bir ipucu:

# This connects to the openbsd ftp site and
# downloads the recursive directory listing.
import pexpect
child = pexpect.spawn ('ftp ftp.openbsd.org')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('noah@example.com')
child.expect ('ftp> ')
child.sendline ('cd pub')
child.expect('ftp> ')
child.sendline ('get ls-lR.gz')
child.expect('ftp> ')
child.sendline ('bye')

11

Paramiko'yu da kontrol edebilirsiniz . Henüz scp modülü yok, ancak sftp'yi tamamen destekliyor.

[EDIT] Üzgünüm, paramiko'dan bahsettiğiniz çizgiyi kaçırdınız. Aşağıdaki modül, paramiko için scp protokolünün bir uygulamasıdır. Paramiko veya kabuklu (python için bildiğim tek ssh uygulamaları) kullanmak istemiyorsanız, bunu kullanarak borular kullanarak düzenli bir ssh oturumu çalıştırmak için yeniden çalışabilirsiniz.

paramiko için scp.py


Ekli çözümün, sftpd çalıştırmasa bile sshd çalıştıran herhangi bir makineye güvenli bir şekilde dosya aktardığını mı söylüyorsunuz? Aradığım şey tam olarak bu, ama yorumunuzdan bunun sadece scp benzeri bir cepheye sftp'yi sarar mı söyleyemem.
Michael Gundlach

2
Bu, PATH'de scp içeren sshd'yi çalıştıran herhangi bir makineyle dosya aktarır (scp ssh spesifikasyonunun bir parçası değildir, ancak oldukça yaygındır). Bu sunucuda "scp -t" yi çağırır ve sftp ile ilgisi olmayan dosyaları aktarmak için scp protokolünü kullanır.
JimB

1
OpenSsh'ın scp uygulamasını model olarak kullandığımı lütfen unutmayın, bu yüzden diğer sürümlerle çalışacağı garanti edilmez. Sshd'nin bazı sürümleri temelde sftp ile aynı olan scp2 protokolünü de kullanabilir.
JimB

Lütfen bu soruyu görebilir misiniz: stackoverflow.com/questions/20111242/… Paramiko'nun alt işlem mi yoksa soket gibi başka bir kuyruklu yıldız mı kullandığını merak ediyorum. Klon / çatal sorunları nedeniyle subprocess.check_output ('ssh blah@blah.com "cat / data / file *") kullanarak bellek sorunları yaşıyorum ve paramiko aynı sorunları olup olmadığını merak ediyorum?
Paul

1
@Paul: bir alt işlem kullanmadığı için paramiko'nun aynı sorunları olmayacak.
JimB

9

Düz bir cevap bulunamadı ve bu "scp.Client" modülü mevcut değil. Bunun yerine, bu bana yakışıyor:

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

Eğer win32 üzerine macun takarsanız, bir pscp (macun scp) alırsınız.

böylece win32'deki os.system hack'ini de kullanabilirsiniz.

(ve putty-agent'ı anahtar yönetimi için kullanabilirsiniz)


üzgünüm bu sadece bir kesmek (ama bir python sınıfına sarabilirsiniz)


'Nix one'ın çalışmasının tek nedeni, yolda SCP'nin olmasıdır; Blauohr'un işaret ettiği gibi, düzeltmek çok zor değil. +1
ojrac

6

Kabuktan scp komutunu kullanmak için paket alt işlemini ve komut çağrısını kullanabilirsiniz.

from subprocess import call

cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))

2
Bu, soru soran tarafından belirtilen temel durumdan ne ölçüde farklıdır? Evet, alt işlem sistem sisteminden daha iyidir, ancak her iki durumda da linux benzeri sistemlerin dışında çalışmaz, şifre istemleri, vb. İle ilgili sorunları vardır.
Foon

5

Bugün itibariyle, en iyi çözüm muhtemelen AsyncSSH

https://asyncssh.readthedocs.io/en/latest/#scp-client

async with asyncssh.connect('host.tld') as conn:
    await asyncssh.scp((conn, 'example.txt'), '.', recurse=True)

1
Selam. AsyncSSH'nin en iyisi olduğu iddiasında bulunuyorsunuz, ancak bu iddiayı desteklemek için bir beyanda bulunabilir misiniz? Belki scp () 'den ya da kullanım durumunuz için ne kadar önemli olduğunu ayırt edin. (Bu, çok daha az kod olduğunu söyledi - en azından örneğinizde)
Scott Prive

2
@Crossfit_and_Beer merhaba. "Muhtemelen en iyisi" dedim, kararın kimseye verilmesine izin vereceğim :) Şu anda AsyncSSH'yi diğer kütüphanelerle karşılaştırmak için fazla zamanım yok. Ama çok hızlı: kullanımı basit, asenkron, bakımı ve bakımı çok güzel ve yararlı, oldukça eksiksiz ve çok iyi belgelenmiş.
Loïc

5

Kumaşa bir göz atın. Aktarma .

from fabric import Connection

with Connection(host="hostname", 
                user="admin", 
                connect_kwargs={"key_filename": "/home/myuser/.ssh/private.key"}
               ) as c:
    c.get('/foo/bar/file.txt', '/tmp/')

2
Daha spesifik olabilir misiniz?
Nick T

4

Bu sorunun sorulmasından bu yana oldukça uzun bir süre geçti ve bu arada, bunun üstesinden gelebilecek başka bir kütüphane ortaya çıktı: Plumbum kütüphanesinde bulunan kopyalama işlevini kullanabilirsiniz :

import plumbum
r = plumbum.machines.SshMachine("example.net")
   # this will use your ssh config as `ssh` from shell
   # depending on your config, you might also need additional
   # params, eg: `user="username", keyfile=".ssh/some_key"`
fro = plumbum.local.path("some_file")
to = r.path("/path/to/destination/")
plumbum.path.utils.copy(fro, to)

Plumbum ile özel anahtarın parolasını nasıl girebilirim? p
ekta

@ekta: Komut satırında sizden istenir. Kendi kodunuzdan sağlamak istiyorsanız, plumbum'un API'sının bunu desteklediğini sanmıyorum. Ancak plumbum'un SshMachineerişimi var ssh-agent, bu yüzden her seferinde yazmaktan kaçınmak istiyorsanız, bunu yapmanın bir yolu var. Ayrıca plumbum'un github sayfasında bir özellik isteği de gönderebilirsiniz.
pmos

3
import paramiko

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

client.connect('<IP Address>', username='<User Name>',password='' ,key_filename='<.PEM File path')

#Setup sftp connection and transmit this script 
print ("copying")

sftp = client.open_sftp() 
sftp.put(<Source>, <Destination>)


sftp.close()

Cevabınıza neden çözümünüzün iyi olduğunu açıklayan bir yorum eklediyseniz ve okuyucuların bunu mevcut diğer çözümlerle karşılaştırmasına yardımcı olmanız yardımcı olacaktır. Sadece kod göndermek her zaman öğrencinin daha iyi çözümleri nasıl tanıyacağını bilmesine yardımcı olmaz.
Brian Tompsett - 莱恩 莱恩

Bu SFTP, SCP değil.
Martin Prikryl

2

* Nix kullanıyorsanız sshpass kullanabilirsiniz

sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path

1

Hmmm, belki başka bir seçenek sshfs ( Mac için de bir sshfs ) gibi bir şey kullanmak olacaktır . Yönlendiriciniz bağlandıktan sonra dosyaları doğrudan kopyalayabilirsiniz. Bunun özel uygulamanız için işe yarayıp yaramadığından emin değilim ama kullanışlı tutmak için güzel bir çözüm.



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.