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

StackOverflow https://stackoverflow.com/questions/68335

  •  09-06-2019
  •  | 
  •  

문제

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

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

도움이 되었습니까?

해결책

간단한 접근 방식을 원한다면 이것이 효과가 있습니다.

먼저 파일을 ".close()"하여 Python에서 디스크로 플러시되었음을 알 수 있습니다.

import os
os.system("scp FILE USER@SERVER:PATH")
#e.g. os.system("scp foo.bar joe@srvr.net:/path/to/foo.bar")

scp가 공개 SSH 키를 사용하여 자동으로 인증되도록(즉, 스크립트에서 비밀번호를 묻지 않도록) 사전에 SSH 키를 생성(소스 머신에서)하고 설치(대상 머신에서)해야 합니다. .

SSH-keygen 예

다른 팁

Python에서 이를 수행하려면(예:scp를 subprocess.Popen 또는 이와 유사한 방식으로 래핑하지 않음) 파라미코 도서관에서는 다음과 같이 할 것입니다:

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

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

아마 당신은 하위 프로세스 모듈.이 같은:

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

어디 destination 아마도 다음과 같은 형태일 것이다 user@remotehost:remotepath.@Charles Duffy 덕분에 SCP 작업을 지정하기 위해 단일 문자열 인수를 사용한 원래 답변의 약점을 지적했습니다. shell=True - 경로의 공백을 처리하지 않습니다.

모듈 문서에는 이 작업과 함께 수행할 수 있는 오류 검사의 예입니다.

다음을 수행할 수 있도록 적절한 자격 증명을 설정했는지 확인하세요. 머신 간 무인, 비밀번호 없는 scp.이있다 이미 이것에 대한 stackoverflow 질문.

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

  1. 명령줄 프로그램 래핑
  2. SSH 기능을 제공하는 Python 라이브러리를 사용합니다(예: - 파라미코 또는 뒤틀린 소라)

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

메모:SSH를 통해 파일을 전송하려는 경우, 특히 대안이 일반 scp인 경우 rsync를 이기기가 어렵습니다.

나는 시스템 호출을 대체하기 위해 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')

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

이를 위해 정확하게 설계된 vassal 패키지를 사용할 수 있습니다.

필요한 것은 vassal을 설치하고 수행하는 것뿐입니다.

from vassal.terminal import Terminal
shell = Terminal(["scp username@host:/home/foo.txt foo_local.txt"])
shell.run()

또한 인증 자격 증명을 저장하므로 반복해서 입력할 필요가 없습니다.

부름 scp 하위 프로세스를 통한 명령은 스크립트 내부에서 진행 보고서를 수신하는 것을 허용하지 않습니다. pexpect 해당 정보를 추출하는 데 사용될 수 있습니다.

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

보다 로컬 네트워크의 Python 복사 파일(linux -> linux)

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

나는 사용했다 sshfs SSH를 통해 원격 디렉토리를 마운트하고 종료 파일을 복사하려면:

$ mkdir ~/sshmount
$ sshfs user@remotehost:/path/to/remote/dst ~/sshmount

그런 다음 파이썬에서:

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

이 방법은 로컬로 캐싱하고 단일 대용량 파일을 보내는 대신 데이터를 생성하는 경우 데이터를 스트리밍할 수 있다는 장점이 있습니다.

SSL 인증서를 사용하지 않으려면 다음을 시도해 보세요.

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

매우 간단한 접근 방식은 다음과 같습니다.

import os
os.system('sshpass -p "password" scp user@host:/path/to/file ./')

Python 라이브러리가 필요하지 않으며(OS만) 작동합니다.

일종의 해킹이지만 다음은 작동합니다 :)

import os
filePath = "/foo/bar/baz.py"
serverPath = "/blah/boo/boom.py"
os.system("scp "+filePath+" user@myserver.com:"+serverPath)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top