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

2025-03-04 08:24:00
admin
原创
91
摘要:问题描述:我的本地机器上有一个文本文件,它是由 cron 中每天运行的 Python 脚本生成的。我想添加一些代码以便通过 SSH 将该文件安全地发送到我的服务器。解决方案 1:要在 Python 中使用Paramiko库执行此操作(即不通过 subprocess.Popen 或类似方法包装 scp),您可以...

问题描述:

我的本地机器上有一个文本文件,它是由 cron 中每天运行的 Python 脚本生成的。

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


解决方案 1:

要在 Python 中使用Paramiko库执行此操作(即不通过 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()

(您可能需要处理未知主机、错误、创建任何必要的目录等等)。

解决方案 2:

你可以使用以下命令调用bash 命令(它通过SSHscp复制文件):subprocess.run

import subprocess
subprocess.run(["scp", FILE, "USER@SERVER:PATH"])
#e.g. subprocess.run(["scp", "foo.bar", "joe@srvr.net:/path/to/foo.bar"])

如果您正在同一个 Python 程序中创建想要发送的文件,您将需要在用于打开文件的块subprocess.run之外调用命令(或者如果您不使用块,则首先调用该文件),这样您就知道它已从 Python 刷新到磁盘。with`.close()`with

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

解决方案 3:

你可能会使用subprocess 模块。像这样:

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 上已经有一个关于此问题的问题。

解决方案 4:

遇到了同样的问题,但不是“黑客攻击”或模拟命令行:

在这里找到了答案。

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

解决方案 5:

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

  1. 包装命令行程序

  2. 使用提供 SSH 功能的 Python 库(例如 - Paramiko或Twisted Conch)

每种方法都有自己的特点。如果您要包装“ssh”、“scp”或“rsync”等系统命令,则需要设置 SSH 密钥以启用无密码登录。您可以使用 Paramiko 或其他库将密码嵌入脚本中,但您可能会发现缺乏文档令人沮丧,特别是如果您不熟悉 SSH 连接的基础知识(例如密钥交换、代理等)。不言而喻,对于这类事情,SSH 密钥几乎总是比密码更好。

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

我曾使用 Paramiko 来替换系统调用,但由于包装命令易于使用且易于理解,我最终还是被它吸引了。你可能不一样。不久前我浏览过 Conch,但它对我没什么吸引力。

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

解决方案 6:

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

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

解决方案 7:

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

解决方案 8:

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

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

不需要 Python 库(只需要操作系统),而且可以正常工作,但是使用此方法需要安装另一个 ssh 客户端。如果在另一个系统上运行,这可能会导致不良行为。

解决方案 9:

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

你只需要安装 vassal 并执行

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

此外,它将保存您的身份验证凭据,无需一次又一次地输入它们。

解决方案 10:

使用外部资源 paramiko;

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

解决方案 11:

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

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

然后在python中:

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

这种方法的优点是,如果您正在生成数据而不是本地缓存并发送单个大文件,则可以传输数据。

解决方案 12:

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

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

解决方案 13:

通过子进程调用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})

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

解决方案 14:

有点黑客,但下面的应该可以工作:)

import os
filePath = "/foo/bar/baz.py"
serverPath = "/blah/boo/boom.py"
os.system("scp "+filePath+" user@myserver.com:"+serverPath)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3892  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2717  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   52  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   54  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   49  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用