如何在 Python 中使用 scp?
- 2025-01-09 08:46:00
- admin 原创
- 88
问题描述:
在 Python 中,scp 文件最符合 Python 风格的方法是什么?我唯一知道的方法是
os.system('scp "%s" "%s:%s"' % (localfile, remotehost, remotefile) )
这是一种黑客行为,它在类 Linux 系统之外无法工作,并且需要 Pexpect 模块的帮助来避免密码提示,除非您已经为远程主机设置了无密码 SSH。
我知道 Twisted 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')
解决方案 1:
尝试使用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客户端代码)
解决方案 2:
您可能有兴趣尝试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')
解决方案 3:
找不到直接的答案,而且这个“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')
解决方案 4:
您还可以查看paramiko。 目前还没有 scp 模块,但它完全支持 sftp。
[编辑] 抱歉,我错过了您提到 paramiko 的那一行。以下模块只是 paramiko 的 scp 协议的实现。如果您不想使用 paramiko 或 conch(据我所知,这是 Python 的唯一 ssh 实现),您可以重新设计它以使用管道在常规 ssh 会话上运行。
paramiko 的 scp.py
解决方案 5:
使用内置 sftp 客户端的简单示例paramiko
。这不仅仅是纯 SCP,而且在底层也使用 SSH,并且只要 SCP 工作,它就应该工作。正如 OP 所述,他的路由器阻止了 SFTP。因此,如果您绝对需要使用 SCP 协议,则此解决方案不适合您。
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()
使用 SFTP 的好处:例如,您将能够列出目录,而不限于 put/get。好处 2,仅使用paramiko
可以减少依赖性。
解决方案 6:
如果您在 win32 上安装 putty,您将获得一个 pscp(putty scp)。
因此您也可以在 win32 上使用 os.system hack。
(您可以使用 putty-agent 进行密钥管理)
抱歉,这只是一个 hack(但你可以将它包装在 python 类中)
解决方案 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)
解决方案 8:
看一下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/')
解决方案 9:
您可以使用包子进程和命令调用从 shell 使用 scp 命令。
from subprocess import call
cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))
解决方案 10:
这个问题已经有一段时间了,与此同时,另一个可以处理这个问题的库出现了:您可以使用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)
解决方案 11:
如果你使用的是 *nix,则可以使用sshpass
sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path
解决方案 12:
嗯,也许另一个选择是使用类似sshfs 的东西(Mac 也有sshfs)。路由器安装完成后,您可以直接复制文件。我不确定这是否适合您的特定应用程序,但这是一个很好的解决方案。
解决方案 13:
不久前,我编写了一个依赖于 paramiko 的 python SCP 复制脚本。它包含用于处理私钥或 SSH 密钥代理连接的代码,并支持密码验证。
http://code.activestate.com/recipes/576810-copy-files-over-ssh-using-paramiko/