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

为何我的SSH子进程串行运行而非并行执行?

问题:SSH进程未并行执行的原因及修复

我的脚本包含两个循环:

  1. 第一个循环为每台远程机器启动多个ssh进程;
  2. 第二个循环收集并打印每个进程的stderr、stdout,并检查其returncode

通过各进程中date命令的输出可确认,所有进程均为串行运行,但我预期它们能并行执行。请问我哪里操作有误?

import os
import locale
import subprocess
import logging

logging.basicConfig(level=logging.INFO)
Nodes = ["node1", "node2", "localhost"]  # 示例节点列表

pipes = {}
myhostname = os.uname()[1].lower()
for node in Nodes:
    if node.lower() == myhostname:
        cmd = '/bin/bash'
    else:
        cmd = ('ssh -q '
            '-o PasswordAuthentication=no '
            '-o StrictHostKeyChecking=no '
            '%s /bin/bash') % node
    pipe = subprocess.Popen(cmd.split(' '),
        stdin = subprocess.PIPE, stdout = subprocess.PIPE,
        stderr = subprocess.PIPE, close_fds = True,
        encoding = locale.getlocale()[1])
    pipe.stdin.write("""
        date
        sleep 1
        date
        exit""")
    pipes[node] = pipe

logging.info('%d processes spawn, collecting outputs', len(pipes))
errCount = 0
for (node, pipe) in pipes.items():
    out, err = pipe.communicate()
    if err:
        logging.warn('%s stderr: %s', node, err.strip())
    if out:
        logging.info('%s stdout: %s', node, out.strip())
    if pipe.returncode != 0:
        errCount += 1
        logging.error('Got exit code %d from %s, increasing '
            'error-count to %d', pipe.returncode, node, errCount)

错误原因

核心问题是向子进程标准输入写入命令后,未关闭stdin。

远程的bash进程收到你写入的命令后,会一直等待更多输入(因为stdin处于打开状态),不会立即执行脚本内容。直到第二个循环调用pipe.communicate()时,该方法才会隐式关闭子进程stdin,此时bash才开始执行命令。而communicate()本身是阻塞调用,会等待当前子进程执行完毕再处理下一个,最终导致所有进程串行运行。

修复方案

在第一个循环中,写完stdin后立即关闭它,让bash进程收到EOF并开始执行命令,这样所有子进程就能并行运行。

修改第一个循环的代码,在pipe.stdin.write(...)后添加pipe.stdin.close():

pipe.stdin.write("""
    date
    sleep 1
    date
    exit""")
pipe.stdin.close()  # 添加这一行,关闭标准输入
pipes[node] = pipe

额外优化建议

  • 可以用subprocess.Popen配合communicate(input=...)传递命令,这样更简洁,也能避免手动管理stdin的问题,但注意不要在第一个循环中直接调用communicate()(会导致串行),仍需先启动所有进程再统一收集结果。
  • 针对大量节点场景,可使用concurrent.futures等并发库管理进程,代码会更简洁易维护。

内容的提问来源于stack exchange,提问作者Mikhail T.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 01:46:20