You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Paramiko执行curl时输出流向异常及Python自动化下载方案咨询

如何优化远程服务器文件下载的自动化流程

问题背景

我原本需要手动通过SSH登录服务器,切换至指定文件夹后执行curl命令下载文件至该文件夹。现尝试通过Python程序自动化此流程,已使用Paramiko实现远程SSH连接并执行命令:

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(credentials)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('cd /path/to/folder/ && sudo curl -H \'X-JFrog-Art-Api:api_key\' -O "https://path/to/download/file.tar.xz"', timeout=600)
print(f'curl ssh_stdout: {ssh_stdout.readlines()}')
print(f'curl ssh_stderr: {ssh_stderr.readlines()}')

文件可成功下载,但预期输出至stdout的内容却出现在stderr中(stderr里全是curl的进度条信息),这种方式不利于自动化流程。请问是否有更适配此类操作的Python库?我考虑使用requests。


解决方案

1. 快速修复:调整curl命令输出

其实不用换库,只要修改curl的参数就能让进度信息不再干扰stderr。curl默认会把进度输出到stderr,你可以:

  • 加上-s参数(静默模式),关闭所有进度和状态输出:
    cd /path/to/folder/ && sudo curl -s -H 'X-JFrog-Art-Api:api_key' -O "https://path/to/download/file.tar.xz"
    
    这样stderr里只会保留真正的错误信息,方便你自动化判断下载是否成功。
  • 如果需要保留进度但想把它转到stdout,可以用重定向:
    cd /path/to/folder/ && sudo curl -# -H 'X-JFrog-Art-Api:api_key' -O "https://path/to/download/file.tar.xz" 2>&1
    
    其中-#会把进度改成条形显示,2>&1将stderr内容重定向到stdout。

2. 更可控的方案:本地用requests下载,再SFTP上传

这是我更推荐的方案,完全摆脱对服务器curl的依赖,还能在本地灵活处理下载逻辑:

import requests
import paramiko

# 1. 本地用requests下载文件
download_url = "https://path/to/download/file.tar.xz"
headers = {"X-JFrog-Art-Api": "api_key"}
local_temp_path = "/tmp/file.tar.xz"

# 流式下载,避免大文件占用过多内存
with requests.get(download_url, headers=headers, stream=True) as response:
    response.raise_for_status()  # 自动处理HTTP错误
    with open(local_temp_path, "wb") as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)

# 2. 用Paramiko的SFTP功能上传到服务器指定目录
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(credentials)

sftp = ssh.open_sftp()
remote_target_path = "/path/to/folder/file.tar.xz"
# 如果需要sudo权限上传,可以先传到临时目录再用sudo移动
# sftp.put(local_temp_path, "/tmp/file.tar.xz")
# ssh.exec_command(f"sudo mv /tmp/file.tar.xz {remote_target_path}")
sftp.put(local_temp_path, remote_target_path)

# 清理资源
sftp.close()
ssh.close()

这个方案的优势是:

  • 能在本地捕获下载过程中的异常(比如网络中断、HTTP 403/404)
  • 可以轻松添加进度监控(比如计算已下载字节数)
  • 不依赖服务器环境的curl版本或配置

3. 更简洁的自动化工具:使用Fabric

如果你经常需要做远程服务器的自动化操作,Fabric是基于Paramiko的高层封装库,语法更简洁,整合了命令执行和文件传输:

from fabric import Connection
import requests

# 初始化远程连接
conn = Connection(
    host=credentials["hostname"],
    user=credentials["username"],
    connect_kwargs={"password": credentials["password"]}
)

# 方案A:远程执行优化后的curl命令
result = conn.sudo('cd /path/to/folder/ && curl -s -H \'X-JFrog-Art-Api:api_key\' -O "https://path/to/download/file.tar.xz"')
print("命令输出:", result.stdout)
print("错误信息:", result.stderr)

# 方案B:本地下载后上传
local_temp_path = "/tmp/file.tar.xz"
with requests.get("https://path/to/download/file.tar.xz", headers={"X-JFrog-Art-Api": "api_key"}, stream=True) as r:
    r.raise_for_status()
    with open(local_temp_path, "wb") as f:
        for chunk in r.iter_content(chunk_size=8192):
            f.write(chunk)

# 直接sudo上传到目标目录
conn.put(local_temp_path, remote="/path/to/folder/file.tar.xz", sudo=True)

Fabric还支持批量操作多台服务器、任务编排等,非常适合运维自动化场景。


内容的提问来源于stack exchange,提问作者runnerpaul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 13:07:41