[python] SCP 또는 SSH를 사용하여 Python에서 원격 서버에 파일을 복사하는 방법은 무엇입니까?

cron에서 실행되는 매일 Python 스크립트에 의해 생성되는 로컬 컴퓨터에 텍스트 파일이 있습니다.

SSH를 통해 해당 파일을 내 서버로 안전하게 전송하기 위해 약간의 코드를 추가하고 싶습니다.



답변

당신은 호출 할 수 있습니다 scpbash는 명령 (이상은 파일을 복사 SSH 로)를 subprocess.run:

import subprocess
subprocess.run(["scp", FILE, "USER@SERVER:PATH"])
#e.g. subprocess.run(["scp", "foo.bar", "joe@srvr.net:/path/to/foo.bar"])

동일한 Python 프로그램에서 보내려는 파일을 생성하는 경우 파일 을 열기 위해 사용 subprocess.run하는 with블록 외부에서 명령 을 호출하고 싶을 것입니다 (또는 .close()파일을 사용하지 않는 경우 먼저 파일을 호출 해야합니다. with블록)이므로 Python에서 디스크로 플러시된다는 것을 알 수 있습니다.

scp가 공개 ssh 키로 자동으로 인증되도록 (즉, 스크립트가 암호를 요청하지 않도록) ssh 키를 미리 생성하고 (소스 시스템에서) 설치 (대상 시스템에)해야합니다. .


답변

Paramiko 라이브러리를 사용하여 Python에서이를 수행하려면 (즉, subprocess.Popen 또는 이와 유사한 것을 통해 scp를 래핑하지 않음) 다음과 같이하면됩니다.

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

(알 수없는 호스트, 오류, 필요한 디렉토리 생성 등을 처리하고 싶을 것입니다.)


답변

아마도 subprocess 모듈을 사용할 것입니다 . 이 같은:

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

어디 destination아마 양식입니다 user@remotehost:remotepath. 단일 문자열 인수를 사용하여 shell=True경로의 공백을 처리하지 않는 단일 문자열 인수를 사용하는 내 원래 답변의 약점을 지적한 @Charles Duffy에게 감사드립니다 .

모듈 설명서에는 이 작업과 함께 수행 할 수있는 오류 검사 예제가 있습니다.

머신간에 무인 암호없는 scp를 수행 할 수 있도록 적절한 자격 증명을 설정했는지 확인합니다 . 이것에 대한 stackoverflow 질문이 이미 있습니다.


답변

문제에 접근하는 방법에는 몇 가지가 있습니다.

  1. 명령 줄 프로그램 래핑
  2. SSH 기능을 제공하는 Python 라이브러리 (예 : Paramiko 또는 Twisted Conch )

각 접근 방식에는 고유 한 단점이 있습니다. “ssh”, “scp”또는 “rsync”와 같은 시스템 명령을 래핑하는 경우 암호없는 로그인을 사용하려면 SSH 키를 설정해야합니다. Paramiko 또는 다른 라이브러리를 사용하여 스크립트에 암호를 포함 할 수 있지만 특히 SSH 연결의 기본 사항 (예 : 키 교환, 에이전트 등)에 익숙하지 않은 경우 문서가 부족하다는 것을 알 수 있습니다. SSH 키가 이런 종류의 암호보다 거의 항상 더 나은 아이디어라는 것은 말할 필요도 없습니다.

참고 : SSH를 통해 파일을 전송할 계획이라면 rsync를 이기기가 어렵습니다. 특히 대안이 일반 오래된 scp 인 경우 더욱 그렇습니다.

저는 Paramiko를 시스템 호출을 대체하기 위해 사용했지만 사용의 용이성과 즉각적인 친숙 함으로 인해 래핑 된 명령에 다시 끌 렸습니다. 당신은 다를 수 있습니다. 나는 얼마 전에 Conch를 한 번 줬지만 그것은 나에게 호소력이 없었습니다.

시스템 호출 경로를 선택하면 Python은 os.system 또는 명령 / 하위 프로세스 모듈과 같은 옵션 배열을 제공합니다. 버전 2.4 이상을 사용하는 경우 하위 프로세스 모듈을 사용합니다.


답변

동일한 문제에 도달했지만 “해킹”또는 에뮬레이션 명령 줄 대신 :

여기 에서이 답변을 찾았 습니다 .

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


답변

이와 같은 작업을 수행하여 호스트 키 검사도 처리 할 수 ​​있습니다.

import os
os.system("sshpass -p password scp -o StrictHostKeyChecking=no local_file_path username@hostname:remote_path")


답변

fabric ssh에 파일을 업로드하는 데 사용할 수 있습니다.

#!/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()