如何使用SCP或SSH将文件复制到Python中的远程服务器?

Alo*_*lok 95 python ssh automation scp

我在本地计算机上有一个文本文件,它由在cron中运行的每日Python脚本生成.

我想添加一些代码,以便通过SSH将该文件安全地发送到我的服务器.

Ton*_*yer 137

要使用Paramiko库在Python中执行此操作(即不通过subprocess.Popen或类似方法包装scp),您可以执行以下操作:

import os
import paramiko

ssh = paramiko.SSHClient() 
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, password=password)
sftp = ssh.open_sftp()
sftp.put(localpath, remotepath)
sftp.close()
ssh.close()
Run Code Online (Sandbox Code Playgroud)

(您可能希望处理未知主机,错误,创建所需的任何目录,等等).

  • paramiko也有一个很好的sftp.put(self,localpath,remotepath,callback = None)函数,所以你不必打开write,并关闭每个文件. (11认同)
  • 注意:为了使这项工作开箱即用,在实例化`ssh`后添加`ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())`. (7认同)
  • 我会注意到SFTP与SCP不是一回事. (5认同)
  • @Drahkar这个问题要求通过SSH发送文件.这就是它的作用. (4认同)
  • 各位,使用服务器密码安全吗?是否有可能使用私钥? (2认同)

pdq*_*pdq 48

如果你想要简单的方法,这应该工作.

你首先想要".close()"这个文件,所以你知道它是从Python刷新到磁盘的.

import os
os.system("scp FILE USER@SERVER:PATH")
#e.g. os.system("scp foo.bar joe@srvr.net:/path/to/foo.bar")
Run Code Online (Sandbox Code Playgroud)

您需要生成(在源计算机上)并预先安装(在目标计算机上)ssh密钥,以便scp自动使用您的公共ssh密钥进行身份验证(换句话说,因此您的脚本不会要求输入密码) .

ssh-keygen示例

  • subprocess.Popen(["scp",filename,"%(user)s @%(server)s:%(remotepath)s"%vars]).wait()是比os.system()更好的方法,它不能正确处理带空格的文件名. (30认同)
  • @CharlesDuffy:`subprocess.check_call(['scp',srcfile,dest])`可以用于Python 2.5而不是`rc = Popen(..).wait(); 如果rc!= 0:raise ..` (3认同)
  • 没关系,发现它.搜索"python格式代码"或"python字符串格式化操作".'%'运算符称为"字符串格式化运算符"或"字符串插值运算符". (2认同)

Bla*_*rad 31

您可能使用子进程模块.像这样的东西:

import subprocess
p = subprocess.Popen(["scp", myfile, destination])
sts = os.waitpid(p.pid, 0)
Run Code Online (Sandbox Code Playgroud)

destination形式可能在哪里user@remotehost:remotepath.感谢@Charles Duffy指出我的原始答案中的弱点,它使用单个字符串参数来指定scp操作shell=True- 它不会处理路径中的空格.

模块文档包含您可能希望与此操作一起执行的错误检查示例.

确保您已设置正确的凭据,以便可以在计算机之间执行无人值守的无密码scp.有一个stackoverflow问题已经存在.

  • 使用subprocess.Popen是正确的事情.传递一个字符串而不是数组(并使用shell = True)是错误的东西,因为它意味着带空格的文件名不能正常工作. (3认同)
  • 代替“ sts = os.waitpid(p.pid,0)”,我们可以使用“ sts = p.wait()”。 (2认同)

小智 11

有几种不同的方法可以解决这个问题:

  1. 包装命令行程序
  2. 使用提供SSH功能的Python库(例如 - ParamikoTwisted Conch)

每种方法都有自己的怪癖.如果要包装"ssh","scp"或"rsync"等系统命令,则需要设置SSH密钥以启用无密码登录.您可以使用Paramiko或其他库在脚本中嵌入密码,但您可能会发现缺少文档令人沮丧,特别是如果您不熟悉SSH连接的基础知识(例如 - 密钥交换,代理等).毫无疑问,SSH密钥几乎总是比这类东西的密码更好.

注意:如果您计划通过SSH传输文件,它很难击败rsync,特别是如果替代方案是普通的旧scp.

我已经使用Paramiko来着眼于替换系统调用,但由于易于使用和即时熟悉,我发现自己被回归到包装的命令.你可能会有所不同.我不久前给了海螺一次,但它并没有吸引我.

如果选择系统调用路径,Python会提供一系列选项,例如os.system或命令/子进程模块.如果使用版本2.4+,我会使用子进程模块.


Mav*_*les 6

达到了同样的问题,但不是"黑客"或模拟命令行:

在这里找到这个答案.

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')
Run Code Online (Sandbox Code Playgroud)

  • 所以,现在是 2018 年,5 月份他们发布了 0.11.0 版。那么,看来 SCPClient 还没有死? (2认同)

小智 6

你也可以做这样的事情来处理主机密钥检查

import os
os.system("sshpass -p password scp -o StrictHostKeyChecking=no local_file_path username@hostname:remote_path")
Run Code Online (Sandbox Code Playgroud)