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

BASH技术问题:如何将标准输入重定向至数量可变的子进程

解决stdin重定向到可变数量子进程的问题

你遇到的核心问题是:bash在数组展开阶段不会重新解析进程替换(>())语法,所以直接把>>()放进数组再传给tee,这些内容只会被当作普通文件名或命令行参数,不会触发进程替换。

下面给两种可行的解决方案:

方案一:用eval强制解析进程替换(适合可控场景)

如果你的子进程命令都是自己可控的(无不可信输入),可以用eval让bash重新解析构造好的命令参数:

# 定义要执行的子进程命令(只存命令和参数,不用加>>())
programs=("exe_1 args_1" "exe_2 args_2" "exe_n args_n")

# 构造tee的进程替换参数
tee_args=()
for cmd in "${programs[@]}"; do
    tee_args+=(">($cmd)")
done

# 用eval执行,让bash解析进程替换
eval "tee ${tee_args[*]} >/dev/null"

⚠️ 注意:如果programs里的内容来自不可信输入,eval会有安全风险,可能被注入恶意代码,这种情况不要用这个方案。

方案二:用文件描述符管理子进程(更安全)

这种方法不需要eval,通过手动创建管道和管理文件描述符来实现,更安全:

# 定义子进程命令列表
programs=("exe_1 args_1" "exe_2 args_2")

# 启动所有子进程,保存它们的输入管道文件描述符
pipes=()
for cmd in "${programs[@]}"; do
    # 创建管道并启动子进程,将管道写入端的文件描述符存入数组
    exec {fd}> >($cmd)
    pipes+=($fd)
done

# 读取stdin的每一行,写入所有子进程的管道
while IFS= read -r line; do
    for fd in "${pipes[@]}"; do
        echo "$line" >&$fd
    done
done

# 关闭所有管道,让子进程正常结束
for fd in "${pipes[@]}"; do
    exec {fd}>&-
done

这个方法的好处是完全避免了eval的安全问题,而且能精准控制每一行输入的分发。

为什么原来的写法不行

bash的语法解析顺序是先处理进程替换、重定向这些特殊语法,再处理数组展开。所以你把>>()放进数组的时候,bash已经完成了语法解析,数组展开后这些内容只会被当作普通字符串传给tee,自然不会触发进程替换,还会把参数里的-开头内容当成tee的选项,导致错误。

内容的提问来源于stack exchange,提问作者Mega-X

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:37:20