如何在python scp?

问题描述 投票:140回答:13

在Python中scp文件的最pythonic方法是什么?我所知道的唯一途径是

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

这是一个hack,并且在类似Linux的系统之外不起作用,并且需要Pexpect模块的帮助以避免密码提示,除非您已经将无密码SSH设置到远程主机。

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

我知道paramiko,一个支持ssh和sftp的Python模块;但它不支持scp。

背景:我正在连接到不支持sftp但支持ssh / scp的路由器,所以sftp不是一个选项。

编辑:这是How to copy a file to a remote server in Python using SCP or SSH?的副本。但是,这个问题没有给出一个scp特定的答案来处理python中的键。我希望有一种运行代码的方式

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')
python ssh scp
13个回答
87
投票

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

(Qazxswpoi)


1
投票

嗯,也许另一个选择是使用类似async with asyncssh.connect('host.tld') as conn: await asyncssh.scp((conn, 'example.txt'), '.', recurse=True) (也有Mac的sshfs)。安装路由器后,您可以直接复制文件。我不确定这是否适用于您的特定应用程序,但它是一个很好的解决方案,以保持方便。


1
投票

我刚才把一个依赖于paramiko的python SCP副本放在一起。它包括用于处理与私钥或SSH密钥代理的连接以及回退到密码身份验证的代码。

sshfs



-2
投票

我不认为你可以轻松下载任何一个模块来实现scp,但是你可能会觉得这很有用:sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path


14
投票

您可能对尝试SCPClient codePexpect)感兴趣。这将允许您处理密码的交互式提示。

以下是主网站上的示例用法(对于ftp):

source code

10
投票

你也可以看看# 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 ('[email protected]') child.expect ('ftp> ') child.sendline ('cd pub') child.expect('ftp> ') child.sendline ('get ls-lR.gz') child.expect('ftp> ') child.sendline ('bye') 。目前还没有scp模块,但它完全支持sftp。

[编辑]抱歉,错过了你提到paramiko的路线。以下模块只是paramiko的scp协议的一个实现。如果你不想使用paramiko或conch(我知道python的唯一ssh实现),你可以重做这个来使用管道运行常规的ssh会话。

paramiko


6
投票

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

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

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


对不起它只是一个黑客(但你可以把它包装在一个python类)


6
投票

找不到直接的答案,这个“scp.Client”模块不存在。相反,scp.py for paramiko适合我:

this

4
投票

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

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
投票

自从提出这个问题以来已经有一段时间了,与此同时,另一个可以解决这个问题的库已经出现了:您可以使用from subprocess import call cmd = "scp user1@host1:files user2@host2:files" call(cmd.split(" ")) 库中包含的copy函数:

Plumbum

4
投票

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

fabric.transfer

3
投票

截至今天,最好的解决方案可能是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/')

AsyncSSH

https://asyncssh.readthedocs.io/en/latest/#scp-client
© www.soinside.com 2019 - 2024. All rights reserved.