it-swarm.cn

如何使用SCP或SSH将文件复制到Python中的远程服务器?

我在本地计算机上有一个文本文件,它由在cron中运行的每日Python脚本生成。

我想添加一些代码,以便通过SSH将该文件安全地发送到我的服务器。

89
Alok

如果你想要简单的方法,这应该工作。

你首先想要“.close()”这个文件,所以你知道它是从Python刷新到磁盘的。

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

您需要生成(在源计算机上)并预先安装(在目标计算机上)ssh密钥,以便scp自动使用您的公共ssh密钥进行身份验证(换句话说,因此您的脚本不会要求输入密码) 。

ssh-keygen示例

45
pdq

要使用 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()

(您可能希望处理未知主机,错误,创建所需的任何目录,等等)。

134
Tony Meyer

您可能使用 subprocess模块​​ 。像这样的东西:

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

destination的形式可能是[email protected]:remotepath。感谢@Charles Duffy指出我的原始答案中的弱点,该答案使用单个字符串参数来指定scp操作Shell=True - 它不会处理路径中的空格。

模块文档具有 您可能希望与此操作一起执行的错误检查示例。

确保您已设置正确的凭据,以便可以在计算机之间执行 无人值守,无密码的scp 。这已经存在 stackoverflow问题

28
Blair Conrad

有几种不同的方法可以解决这个问题:

  1. 包装命令行程序
  2. 使用提供SSH功能的Python库(例如 - ParamikoTwisted Conch

每种方法都有自己的怪癖。如果要包装“ssh”,“scp”或“rsync”等系统命令,则需要设置SSH密钥以启用无密码登录。您可以使用Paramiko或其他库在脚本中嵌入密码,但您可能会发现缺少文档令人沮丧,特别是如果您不熟悉SSH连接的基础知识(例如 - 密钥交换,代理等)。毫无疑问,SSH密钥几乎总是比这类东西的密码更好。

注意:如果您计划通过SSH传输文件,它很难击败rsync,特别是如果替代方案是普通的旧scp。

我已经使用了Paramiko来关注更换系统调用,但由于易于使用和直接熟悉,我发现自己被回归到包装的命令。你可能会有所不同。我不久前给了海螺一次,但它并没有吸引我。

如果选择系统调用路径,Python提供了一系列选项,如os.system或命令/子进程模块。如果使用版本2.4+,我会使用子进程模块。

11
Michael

达到了同样的问题,但不是“黑客”或模拟命令行:

找到这个答案 这里

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

您可以使用专为此设计的vassal包。

你所需要的只是安装vassal并做

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

此外,它将为您节省身份验证凭据,而无需一次又一次地键入它们。

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

一个非常简单的方法如下:

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

不需要python库(只有操作系统),它的工作原理

0
Roberto Marzocchi

如果您不想使用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!')
0
JavDomGom

我使用 sshfs 通过ssh挂载远程目录,使用 shutil 复制文件:

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

然后在python中:

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

此方法的优点是,如果要生成数据而不是本地缓存并发送单个大文件,则可以流式传输数据。

0
Jonno_FTW

通过子进程调用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 copy文件(linux - > linux)

0
jfs