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

不使用子shell实现函数stdout/stderr分存与合并日志输出

解决方案

要满足你的需求——在当前shell执行函数、分别保存stdout/stderr到单独日志、同时按原输出顺序合并到combined.log——可以用以下写法:

v=1

fun() {
    v=2
    echo out1
    >&2 echo err1
    echo out2
    >&2 echo err2
}

{
    fun > >(tee out.log) 2> >(tee err.log >&2)
} >combined.log

验证效果

执行后:

  • 全局变量v的值变为2,说明函数未在子shell中运行
  • out.log内容:
    out1
    out2
    
  • err.log内容:
    err1
    err2
    
  • combined.log内容(顺序与函数输出完全一致):
    out1
    err1
    out2
    err2
    

原理说明

  1. 避免子shell:整个函数执行逻辑未被包裹在()或管道左侧(这些会触发子shell),函数直接在当前shell环境运行,因此能修改全局变量v。
  2. 分流stdout/stderr:
    • fun > >(tee out.log):将函数的stdout通过tee命令同时写入out.log和当前的stdout流
    • 2> >(tee err.log >&2):将函数的stderr通过tee命令同时写入err.log,并通过>&2将复制后的stderr流放回原stderr通道
  3. 合并输出到combined.log:外层的{ ... } >combined.log将经过tee处理后的stdout和stderr流合并写入combined.log,由于bash会按输出产生的先后顺序处理流,因此能完美保留原输出顺序。

为什么之前的写法无效

  • 初始写法fun >out.log 2>err.log &>combined.log:bash重定向是从左到右解析的,&>combined.log会覆盖之前的>out.log和2>err.log,导致只有combined.log有内容。
  • 你编辑后的嵌套重定向写法:由于stdout和stderr分别通过两个独立的tee进程处理,不同进程的缓冲机制可能导致输出顺序错乱,无法保证原有的输出时序。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:17:12