파이썬에서 scp하는 방법?


158

파이썬에서 파일을 scp하는 가장 파이썬적인 방법은 무엇입니까? 내가 아는 유일한 길은

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

이것은 해킹이며 Linux와 같은 시스템 외부에서는 작동하지 않으며 원격 호스트에 비밀번호가없는 SSH를 설정하지 않은 경우 비밀번호 프롬프트를 피하기 위해 Pexpect 모듈의 도움이 필요합니다.

Twisted 's를 알고 conch있지만 저수준 ssh 모듈을 통해 직접 scp를 구현하지 않는 것이 좋습니다.

paramikoSSH와 SFTP를 지원하는 Python 모듈을 알고 있습니다 . 그러나 SCP를 지원하지 않습니다.

배경 : SFTP는 지원하지 않지만 SSH / SCP는 지원하는 라우터에 연결하고 있으므로 SFTP는 옵션이 아닙니다.

편집 : 이것은 SCP 또는 SSH를 사용하여 Python에서 원격 서버로 파일을 복사하는 방법 의 복제본 입니까? . 그러나 그 질문은 파이썬 내에서 키를 다루는 scp 특정 답변을 제공하지 않습니다. 비슷한 코드를 실행하는 방법을 기대하고 있습니다.

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

답변:


106

Paramiko 용 Python scp 모듈을 사용해보십시오 . 사용하기 매우 쉽습니다. 다음 예를 참조하십시오.

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

그런 다음 전화 scp.get()하거나 scp.put()SCP 작업을 수행하십시오.

( SCPClient 코드 )


3
모듈이 실제로 paramiko를 사용하지 않는 것을 제외하고는 결국 * nix에서만 작동 scp하는 scp명령 줄을 실제로 호출 하는 많은 코드입니다 .
Nick Bastin

8
소스 코드에서보고있는 것은 scp -tor를 원격으로 호출 scp -f하는 것입니다 (이 서버 측용으로 존재하는 'to'및 'from'모드). 이것은 본질적으로 scp의 작동 방식입니다. 서버에 존재하는 다른 scp 사본에 의존합니다. 이 기사는 그것을 잘 설명합니다 : blogs.oracle.com/janp/entry/how_the_scp_protocol_works
laher

8
이 솔루션은 다음 두 가지주의 사항으로 작동했습니다. 1. 다음은 내가 사용한 import 문입니다. import paramiko from scp import SCPClient2. 다음은 scp.get () 명령의 예입니다.scp.get(r'/nfs_home/appers/xxxx/test2.txt', r'C:\Users\xxxx\Desktop\MR_Test')
Chris Nielsen

이것은 훌륭하게 작동 할뿐만 아니라 SSH 키가있는 경우이를 활용합니다.
Marcel Wilson

pip install scp이 글을 쓰는 시점에서 0.10.2의 PyPI 에서도이 lib를 설치할 수 있습니다 .
Andrew B.

15

Pexpect ( 소스 코드 ) 시도에 관심이있을 수 있습니다 . 이렇게하면 암호에 대한 대화식 프롬프트를 처리 할 수 ​​있습니다.

다음은 기본 웹 사이트의 사용법 예제 (ftp의 경우)입니다.

# 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를 확인할 수 있습니다 . scp 모듈 (아직)은 없지만 sftp를 완전히 지원합니다.

[편집] 죄송합니다. paramiko를 언급 한 줄을 놓쳤습니다. 다음 모듈은 단순히 paramiko에 대한 scp 프로토콜의 구현입니다. paramiko 또는 conch (파이썬에 대해 알고있는 유일한 ssh 구현)를 사용하지 않으려면 파이프를 사용하여 일반 ssh 세션을 실행하도록이를 재 작업 할 수 있습니다.

paramiko의 scp.py


첨부 된 솔루션이 sftpd를 실행하지 않더라도 sshd를 실행하는 모든 시스템으로 파일을 안전하게 전송한다고 말하고 있습니까? 정확히 내가 찾고있는 것이지만, 이것이 scp와 같은 외관으로 sftp를 감싸는 지 여부를 귀하의 의견에서 알 수 없습니다.
Michael Gundlach

2
이것은 sshd를 실행하는 모든 컴퓨터에서 파일을 전송합니다. sshd는 PATH에 scp를 가지고 있습니다 (scp는 ssh 사양의 일부가 아니지만 상당히 보편적입니다). 이것은 서버에서 "scp -t"를 호출하고 scp 프로토콜을 사용하여 sftp와 관련이없는 파일을 전송합니다.
JimB

1
모델로 openssh의 scp 구현을 사용 했으므로 다른 버전에서는 작동하지 않을 수 있습니다. sshd의 일부 버전은 기본적으로 sftp와 동일한 scp2 프로토콜을 사용할 수도 있습니다.
JimB

이 질문을 볼 수 있습니까 : stackoverflow.com/questions/20111242/… paramiko가 하위 프로세스를 사용하는지 아니면 소켓과 같은 것을 사용하는지 궁금합니다. 복제 / 포크 문제로 인해 subprocess.check_output ( 'ssh blah@blah.com "cat / data / file *")을 사용하여 메모리 문제가 있고 paramiko에 동일한 문제가 있는지 궁금합니다.
Paul

1
@Paul : paramiko는 하위 프로세스를 사용하지 않기 때문에 동일한 문제가 없습니다.
JimB

9

정답을 찾지 못했습니다.이 "scp.Client"모듈이 없습니다. 대신, 이것은 나에게 적합합니다.

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

win32에 putty를 설치하면 pscp (putty scp)가 표시됩니다.

win32에서도 os.system hack을 사용할 수 있습니다.

(그리고 키 관리에 퍼티 에이전트를 사용할 수 있습니다)


미안하지만 그것은 해킹 일뿐입니다 (그러나 파이썬 클래스로 포장 할 수는 있습니다)


'닉스가 일하는 유일한 이유는, 당신은 길에 SCP가 있다는 것입니다; Blauohr이 지적했듯이 해결하기가 어렵지 않습니다. +1
ojrac

6

패키지 서브 프로세스 및 명령 호출을 사용하여 쉘에서 scp 명령을 사용할 수 있습니다.

from subprocess import call

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

2
질문자가 언급 한 기본 사례와 실제로 어떻게 다른가요? 예, 하위 프로세스는 os.system보다 낫지 만 두 경우 모두 Linux와 같은 시스템 외부에서는 작동하지 않으며 암호 프롬프트 등에 문제가 있습니다.
Foon

5

오늘날 가장 좋은 해결책은 아마도 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
안녕하세요. AsyncSSH가 최고라고 주장하지만이 주장을 뒷받침 할 진술을 할 수 있습니까? scp ()와 구별하거나 유스 케이스에 중요한 방식 일 수 있습니다. (이것은 코드가 훨씬 적습니다-적어도 귀하의 예에서는)
Scott Prive

2
@Crossfit_and_Beer 안녕하세요. 그래서 "아마도 최고"라고 말하면서 누구에게나 판단을 내릴 것입니다 :) 지금은 AsyncSSH를 다른 라이브러리와 비교할 시간이별로 없습니다. 그러나 매우 빠르게 : 사용하기 쉽고 비동기 적이며 유지 관리되며 유지 관리가 매우 훌륭하고 도움이되며 매우 완벽하고 잘 문서화되어 있습니다.
Loïc

5

fabric.transfer를 살펴 보십시오 .

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
좀 더 구체적으로 말씀해 주시겠습니까?
Nick T

4

이 질문을 한 지 꽤 오래 걸렸으며 그 동안 이것을 처리 할 수있는 다른 라이브러리가 잘 렸습니다 .Plumbum 라이브러리에 포함 된 복사 기능을 사용할 수 있습니다 .

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으로 개인 키의 암호를 어떻게 입력합니까? p
ekta

@ekta : 명령 행에 프롬프트가 표시됩니다. 자신의 코드에서 제공하려는 경우 plumbum의 API가 이것을 지원한다고 생각하지 않습니다. 그러나 plumbum SshMachine은에 액세스 할 수 ssh-agent있으므로 매번 입력하지 않으려면 한 가지 방법입니다. plumbum의 github 페이지에서 기능 요청을 제출할 수도 있습니다.
pmos

2

* nix를 사용하는 경우 sshpass 를 사용할 수 있습니다

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

2
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()

솔루션이 왜 좋은지 설명하고 독자가 솔루션을 사용 가능한 다른 솔루션과 비교하는 데 도움이되는 해설을 추가하면 도움이 될 것입니다. 코드를 게시한다고해서 항상 학습자가 더 나은 솔루션을 인식하는 방법을 아는 데 도움이되는 것은 아닙니다.
Brian Tompsett-汤 莱恩

이것은 SCP가 아니라 SFTP입니다.
마틴 Prikryl

1

흠, 아마도 또 다른 옵션은 sshfs 와 같은 것을 사용하는 것 입니다 (Mac의 경우 sshfs 도 있습니다). 라우터가 마운트되면 파일을 바로 복사 할 수 있습니다. 특정 응용 프로그램에서 작동하는지 확실하지 않지만 편리하게 유지하는 것이 좋습니다.



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.