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

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

How to copy a file to a remote server in Python using SCP or SSH?

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

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


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

1
2
3
4
5
6
7
8
9
10
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()

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


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

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

1
2
3
import os
os.system("scp FILE USER@SERVER:PATH")
#e.g. os.system("scp foo.bar joe@srvr.net:/path/to/foo.bar")

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

ssh-keygen示例


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

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

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

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

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


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

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

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

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

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


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

    在这里找到这个答案。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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')

    您可以执行类似的操作,以处理主机密钥检查

    1
    2
    import os
    os.system("sshpass -p password scp -o StrictHostKeyChecking=no local_file_path username@hostname:remote_path")


    fabric可用于通过ssh上传文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/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()

    您可以使用专为此设计的vassal包。

    你所需要的只是安装vassal并做

    1
    2
    3
    from vassal.terminal import Terminal
    shell = Terminal(["scp username@host:/home/foo.txt foo_local.txt"])
    shell.run()

    此外,它将为您节省身份验证凭据,而无需一次又一次地键入它们。


    如果您不想使用SSL证书,请尝试此操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import subprocess

    try:
        # Set scp and ssh data.
        connUser = 'john'
        connHost = 'my.host.com'
        connPath = '/home/john/'
        connPrivateKey = '/home/user/myKey.pem'

        # Use scp to send file from local to host.
        scp = subprocess.Popen(['scp', '-i', connPrivateKey, 'myFile.txt', '{}@{}:{}'.format(connUser, connHost, connPath)])

    except CalledProcessError:
        print('ERROR: Connection to host failed!')

    我使用sshfs通过ssh挂载远程目录,并使用shutil复制文件:

    1
    2
    $ mkdir ~/sshmount
    $ sshfs user@remotehost:/path/to/remote/dst ~/sshmount

    然后在python中:

    1
    2
    import shutil
    shutil.copy('a.txt', '~/sshmount')

    此方法的优点是,如果要生成数据而不是本地缓存并发送单个大文件,则可以流式传输数据。


    一个非常简单的方法如下:

    1
    2
    import os
    os.system('sshpass -p"password" scp user@host:/path/to/file ./')

    不需要python库(只有操作系统),它的工作原理


    使用外部资源paramiko;

    1
    2
    3
    4
    5
    6
    7
    8
    9
        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')

    通过子进程调用scp命令不允许在脚本中接收进度报告。 pexpect可用于提取该信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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})

    查看本地网络中的python copy文件(linux - > linux)


    有点hacky,但以下应该工作:)

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


    推荐阅读

      linux计算机的命令?

      linux计算机的命令?,系统,工作,信息,设备,技术,命令,网站,管理,灵活,基础,lin

      vim运行linux命令?

      vim运行linux命令?,系统,工作,信息,地址,命令,标准,时间,情况,工具,基础,linu

      linux下并行运行命令?

      linux下并行运行命令?,系统,服务,工作,命令,环境,网络,暂停,文件,脚本,参数,l

      linux下并行运行命令?

      linux下并行运行命令?,系统,服务,工作,命令,环境,网络,暂停,文件,脚本,参数,l

      linux命令行后台运行?

      linux命令行后台运行?,服务,状态,标准,暂停,命令,后台,连续,地方,工作,方法,l

      linux用计算器的命令?

      linux用计算器的命令?,代码,环境,情况,异常,工具,数据,位置,平台,精密,设计,

      脚本运行linux命令?

      脚本运行linux命令?,系统,环境,工具,工作,位置,底部,代码,发行,官网,终端,lin

      linux进程运行命令?

      linux进程运行命令?,系统,工作,状态,地址,信息,进程,基础,命令,管理,软件,lin

      文件复制命令linux?

      文件复制命令linux?,系统,地址,文件,目录,位置,工具,命令,目标,文件名,源文

      linux显示运行命令?

      linux显示运行命令?,系统,服务,状态,信息,工具,数据,电脑,标准,管理,时间,如

      linux运行vim命令?

      linux运行vim命令?,系统,工具,官方网站,模式,基础,数据,代码,环境,入口,命令

      linux监控命令运行?

      linux监控命令运行?,系统,工作,地址,信息,工具,情况,标准,环境,命令,状态,lin

      linux的数学计算命令?

      linux的数学计算命令?,工作,系统,信息,地址,数字,目录,命令,百分比,情况,管

      linux中命令停止运行?

      linux中命令停止运行?,系统,代码,第一,命令,进程,指令,程序,方法,接线,硬盘,l

      linux自动运行命令?

      linux自动运行命令?,服务,系统,时间,代码,周期性,第一,命令,管理,在线,状态,l

      linux开启运行命令?

      linux开启运行命令?,系统,服务,工作,管理,状态,命令,标准,情况,环境,工具,lin

      linux运行wps命令?

      linux运行wps命令?,软件,官网,名称,时间,电脑,系统,工具,环境,项目,数据,wps

      linux云计算查看命令?

      linux云计算查看命令?,系统,信息,地址,工作,命令,情况,标准,服务,软件,网络,l

      linux运行cmd命令?

      linux运行cmd命令?,电脑,系统,状态,情况,环境,命令,单位,管理,设备,数据,电脑

      linux打开计算器命令?

      linux打开计算器命令?,密码,电脑,工作,设备,数字,系统,手机,指数,情况,服务,