问题:如何在python中进行scp?
在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')
回答 0
尝试使用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)
回答 1
您可能对尝试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')
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 ('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')
回答 2
您也可以查看paramiko。还没有scp模块,但是它完全支持sftp。
[EDIT]抱歉,错过了提到paramiko的那一行。以下模块只是paramiko的scp协议的实现。如果您不想使用paramiko或conch(我知道用于python的唯一ssh实现),则可以对其进行重做以使用管道在常规ssh会话上运行。
scp.py for paramiko
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
回答 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')
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')
回答 4
如果在win32上安装腻子,则会得到一个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)
回答 5
您可以使用包子进程和命令调用来从外壳程序使用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(" "))
回答 6
回答 7
看一下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/')
回答 8
自问这个问题以来已经有一段时间了,与此同时,另一个可以处理此问题的库也出现了:您可以使用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)
回答 9
如果您使用* 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
回答 10
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()
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()
回答 11
嗯,也许另一个选择是使用sshfs之类的东西(Mac也有sshfs)。路由器安装后,您可以直接复制文件。我不确定这是否适用于您的特定应用程序,但这是一个方便的好方法。
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.
回答 12
回答 13