如何在Python中进行scp?

发布于 2024-07-08 07:48:17 字数 1018 浏览 10 评论 0原文

在 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。

编辑: 这是 如何使用 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')

What's the most pythonic way to scp a file in Python? The only route I'm aware of is

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

which is a hack, and which doesn't work outside Linux-like systems, and which needs help from the Pexpect module to avoid password prompts unless you already have passwordless SSH set up to the remote host.

I'm aware of Twisted's conch, but I'd prefer to avoid implementing scp myself via low-level ssh modules.

I'm aware of paramiko, a Python module that supports SSH and SFTP; but it doesn't support SCP.

Background: I'm connecting to a router which doesn't support SFTP but does support SSH/SCP, so SFTP isn't an option.

EDIT:
This is a duplicate of How to copy a file to a remote server in Python using SCP or SSH?. However, that question doesn't give an scp-specific answer that deals with keys from within Python. I'm hoping for a way to run code kind of like

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

少钕鈤記 2024-07-15 07:48:17

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

SCPClient 代码

Try the Python scp module for Paramiko. It's very easy to use. See the following example:

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

Then call scp.get() or scp.put() to do SCP operations.

(SCPClient code)

哽咽笑 2024-07-15 07:48:17

您可能有兴趣尝试 Pexpect (Pexpect) com/pexpect/pexpect" rel="nofollow noreferrer">源代码)。 这将允许您处理密码的交互式提示。

以下是来自主网站的示例用法(用于 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 ('[email protected]')
child.expect ('ftp> ')
child.sendline ('cd pub')
child.expect('ftp> ')
child.sendline ('get ls-lR.gz')
child.expect('ftp> ')
child.sendline ('bye')

You might be interested in trying Pexpect (source code). This would allow you to deal with interactive prompts for your password.

Here's a snip of example usage (for ftp) from the main website:

# 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')
娇女薄笑 2024-07-15 07:48:17

找不到直接的答案,并且这个“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')

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')
心在旅行 2024-07-15 07:48:17

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

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

paramiko 的 scp.py

You could also check out paramiko. There's no scp module (yet), but it fully supports sftp.

[EDIT]
Sorry, missed the line where you mentioned paramiko.
The following module is simply an implementation of the scp protocol for paramiko.
If you don't want to use paramiko or conch (the only ssh implementations I know of for python), you could rework this to run over a regular ssh session using pipes.

scp.py for paramiko

寒江雪… 2024-07-15 07:48:17

使用 paramiko 内置 sftp 客户端的简单示例。 这不仅仅是纯粹的 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 的好处:例如,您将能够列出目录,而不是仅限于放置/获取。 好处 2,仅使用 paramiko 可以减少依赖性。

Simple example using paramiko's built in sftp client. That is not pure SCP only, but uses SSH below the surface as well, and should work whenever SCP works. As the OP states, his router prevents SFTP. So, if you absolutly need to use the SCP protocol, this solution is not for you.

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

Bonus using SFTP: you'll be able to list dirs for example, instead of being limited to put/get. Bonus 2, using only paramiko is reducing dependencies.

甜点 2024-07-15 07:48:17

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

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

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


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

if you install putty on win32 you get an pscp (putty scp).

so you can use the os.system hack on win32 too.

(and you can use the putty-agent for key-managment)


sorry it is only a hack
(but you can wrap it in a python class)

想你只要分分秒秒 2024-07-15 07:48:17

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

As of today, the best solution is probably 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)
辞别 2024-07-15 07:48:17

查看 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/')

Have a look at 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/')
野侃 2024-07-15 07:48:17

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

from subprocess import call

cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))

You can use the package subprocess and the command call to use the scp command from the shell.

from subprocess import call

cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))
和影子一齐双人舞 2024-07-15 07:48:17

自从提出这个问题以来已经有一段时间了,与此同时,另一个可以处理这个问题的库已经出现:
您可以使用复制功能包含在 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)

It has been quite a while since this question was asked, and in the meantime, another library that can handle this has cropped up:
You can use the copy function included in the Plumbum library:

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)
遥远的绿洲 2024-07-15 07:48:17

如果您使用 *nix,则可以使用 sshpass

sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path

If you are on *nix you can use sshpass

sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path
染墨丶若流云 2024-07-15 07:48:17

嗯,也许另一种选择是使用类似 sshfs (有一个 sshfs 对于 Mac 也是如此)。 安装路由器后,您只需直接复制文件即可。 我不确定这是否适用于您的特定应用程序,但这是一个方便携带的好解决方案。

Hmmm, perhaps another option would be to use something like sshfs (there an sshfs for Mac too). Once your router is mounted you can just copy the files outright. I'm not sure if that works for your particular application but it's a nice solution to keep handy.

狼亦尘 2024-07-15 07:48:17

我不久前编写了一个依赖于 paramiko 的 python SCP 复制脚本。 它包含用于处理与私钥或 SSH 密钥代理的连接的代码,并回退到密码身份验证。

http://code.activestate.com/recipes/ 576810-通过-ssh-使用-paramiko复制文件/

I while ago I put together a python SCP copy script that depends on paramiko. It includes code to handle connections with a private key or SSH key agent with a fallback to password authentication.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文