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

我的本地机器上有一个由cron运行的每日Python脚本生成的文本文件。

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

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

您将首先“.close()”文件,以便您知道它是从Python刷新到磁盘的。

import os os.system("scp FILE USER@SERVER:PATH") #eg os.system("scp foo.bar joe@srvr.net:/path/to/foo.bar") 

您需要生成(在源机器上)并在目标机器上安装一个ssh密钥,以便scp能够自动使用您的公共ssh密钥进行身份validation(换句话说,您的脚本不会要求input密码) 。

ssh-keygen的例子

要在Python中执行此操作(例如,不通过subprocess.Popen或类似的方法包装scram),你可以这样做:

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

(你可能想要处理未知的主机,错误,创build必要的目录,等等)。

你可能会使用子stream程模块 。 像这样的东西:

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

destination地址可能是user@remotehost:remotepath 。 感谢@Charles Duffy指出了我原来的答案中的弱点,它使用单个string参数来指定scp操作shell=True – 这不会处理path中的空白。

模块文档有错误检查的例子,你可能想要结合这个操作来执行。

确保您已经设置了适当的凭据,以便您可以在机器之间执行无人值守,无密码的scp 。 这有一个stackoverflow问题 。

有几种不同的方式来解决这个问题:

  1. 包装命令行程序
  2. 使用提供SSHfunction的Python库(例如 – Paramiko或Twisted Conch )

每种方法都有自己的怪癖。 如果您打包系统命令(如“ssh”,“scp”或“rsync”),则需要设置SSH密钥以启用无密码login。 您可以使用Paramiko或其他库在脚本中embedded密码,但是您可能会发现缺乏文档令人沮丧的情况,尤其是在您不熟悉SSH连接的基础知识(例如密钥交换,代理等)的情况下。 这可能不用说,SSH密钥几乎总是比这种东西的密码更好的主意。

注意:如果您计划通过SSH传输文件,那么很难打败rsync,尤其是如果替代scheme是普通的旧式scp。

我已经用Paramiko来replace系统调用,但由于易于使用和直接熟悉,我发现自己已经回到了包装的命令。 你可能会不一样 前段时间我曾经给过海螺,但这并没有吸引我。

如果select系统调用path,Python将提供一系列选项,如os.system或命令/subprocess模块。 如果使用版本2.4+,我会使用subprocess模块。

达到同样的问题,而不是“黑客”或模拟命令行:

在这里find这个答案。

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

fabric可以用来上传文件到SSH:

 #!/usr/bin/env python from fabric.api import execute, put from fabric.network import disconnect_all if __name__=="__main__": import sys # specify hostname to connect to and the remote/local paths srcdir, remote_dirname, hostname = sys.argv[1:] try: s = execute(put, srcdir, remote_dirname, host=hostname) print(repr(s)) finally: disconnect_all() 

通过subprocess调用scp命令不允许在脚本内接收进度报告。 可以使用pexpect来提取该信息:

 import pipes import re import pexpect # $ pip install pexpect def progress(locals): # extract percents print(int(re.search(br'(\d+)%$', locals['child'].after).group(1))) command = "scp %s %s" % tuple(map(pipes.quote, [srcfile, destination])) pexpect.run(command, events={r'\d+%': progress}) 

请参阅本地networking中的Python复制文件(linux – > linux)

 from paramiko import SSHClient from scp import SCPClient import os ssh = SSHClient() ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts"))) ssh.connect(server, username='username', password='password') with SCPClient(ssh.get_transport()) as scp: scp.put('test.txt', 'test2.txt') 

有点哈克,但下面应该工作:)

 import os filePath = "/foo/bar/baz.py" serverPath = "/blah/boo/boom.py" os.system("scp "+filePath+" user@myserver.com:"+serverPath)