191

在 Python 中 scp 文件的最 Pythonic 方式是什么?我知道的唯一路线是

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

这是一种 hack,在类 Linux 系统之外无法使用,并且需要 Pexpect 模块的帮助以避免密码提示,除非您已经为远程主机设置了无密码 SSH。

我知道 Twisted's conch,但我宁愿避免自己通过低级 ssh 模块实现 scp 。

我知道paramiko,一个支持 SSH 和 SFTP 的 Python 模块;但它不支持SCP。

背景:我连接到一个不支持 SFTP 但支持 SSH/SCP 的路由器,所以 SFTP 不是一个选项。

编辑:这是如何使用 SCP 或 SSH 将文件复制到 Python 中的远程服务器的副本?. 但是,该问题并没有给出处理 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')
4

13 回答 13

140

试试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操作。

SCP客户端代码

于 2010-11-26T03:03:37.770 回答
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')
于 2008-10-30T16:18:00.707 回答
13

Couldn't find a straight answer, and this "scp.Client" module doesn't exist. Instead, this suits me:

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')
于 2016-07-24T20:14:37.957 回答
11

您也可以查看paramiko。还没有 scp 模块,但它完全支持 sftp。

[编辑] 对不起,错过了你提到 paramiko 的那一行。以下模块只是 paramiko 的 scp 协议的实现。如果您不想使用 paramiko 或 conch(我所知道的唯一用于 python 的 ssh 实现),您可以重新设计它以使用管道在常规 ssh 会话上运行。

用于 paramiko 的 scp.py

于 2008-10-30T20:22:43.570 回答
8

如果你在 win32 上安装 putty,你会得到一个 pscp(putty scp)。

所以你也可以在 win32 上使用 os.system hack。

(您可以使用 putty-agent 进行密钥管理)


抱歉,这只是一个 hack(但你可以将它包装在 python 类中)

于 2008-10-30T14:42:42.257 回答
7

截至今天,最好的解决方案可能是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)
于 2018-05-19T08:40:26.163 回答
6

您可以使用包子进程和命令调用来使用 shell 中的 scp 命令。

from subprocess import call

cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))
于 2017-02-07T16:18:23.797 回答
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/')
于 2011-11-23T19:30:26.523 回答
5
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()
于 2020-01-22T08:36:10.940 回答
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)
于 2014-07-05T14:08:32.797 回答
2

如果您在 *nix 上,您可以使用sshpass

sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path
于 2014-06-04T23:26:21.943 回答
1

嗯,也许另一种选择是使用sshfs之类的东西(Mac 也有sshfs)。安装路由器后,您可以直接复制文件。我不确定这是否适用于您的特定应用程序,但它是一个很好的解决方案,便于使用。

于 2008-10-30T16:20:46.850 回答
1

我前段时间整理了一个依赖于 paramiko 的 python SCP 复制脚本。它包括处理与私钥或 SSH 密钥代理的连接的代码,并回退到密码身份验证。

http://code.activestate.com/recipes/576810-copy-files-over-ssh-using-paramiko/

于 2012-05-21T13:03:59.717 回答