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

如何将stdout和stderr分别管道给不同进程且保留终端显示及异常排查

问题原因

这个问题是Bash重定向的执行顺序和进程替换的文件描述符继承规则共同导致的:

  1. Bash处理重定向是严格按照从左到右的顺序执行的,你的代码里先完成了stdout(1)到第一个tee进程的重定向,再处理stderr(2)的重定向。
  2. 进程替换(>()包裹的部分)生成的子进程,会继承当前shell已经设置好的所有文件描述符。
  3. 处理stderr的第二个tee进程,默认会把输入的内容分成两份:一份发给后面的cat > err.log写入日志,另一份输出到自己的stdout。而此时子进程继承的stdout已经被重定向到了处理stdout的第一个tee的输入链路,所以这部分内容最终会被写入out.log。

你去掉tee之后两个日志正常,是因为此时处理stderr的子进程是cat > err.log,它不会向自己的stdout输出任何内容,就算stdout已经被重定向也不会产生额外的数据流。

修复方案

只需要让处理stderr的tee进程,把要输出到终端的内容重定向到真实的stderr,而不是默认的stdout即可,修改后的代码如下:

#!/usr/bin/env bash

set -e

function generate_output() {
  echo This message goes to stderr 1>&2
  echo This message goes to stdout
}

generate_output \
    1> >(tee <&0 >(cat > out.log)) \
    2> >(tee <&0 >(cat > err.log) >&2)

修改点仅为在处理stderr的tee进程末尾添加了>&2,指定tee的输出目标为stderr,不会再流入stdout的处理链路。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 13:54:02