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

Bash函数在source与fork执行时stdout输出异常问题排查

Bash脚本source执行与直接运行结果不一致问题排查

我写了个用于测试的Bash脚本initial-tests.bash,它通过source引入scripts/_functions.bash里的函数,这个脚本又被main.bash通过source调用。直接执行source scripts/initial-tests.bash时,测试输出符合预期;但运行bash main.bash时,do_check函数本该返回空结果却输出了false,两种执行方式结果不一样,求原因。

相关脚本代码

initial-tests.bash

#! /bin/bash

source ./scripts/_functions.bash

check=$(do_check)

echo "$check"

_functions.bash

#! /bin/bash
# Here we save reusable functions to aid the other scripts

echoerr() {
    # Output to stderr while freeing stdout for returns
    echo -ne $red
    echo "ERROR: $*" | ts '[%Y-%m-%d %H:%M:%S]' 1>&2
    echo -ne $nc
}

first_check() {
  echoerr "This is an echoerr with echo -e"
  echo false
}

do_check() {
  local x
  x=$(first_check)

  if [[ "$x" = 'false' ]]; then
    echo
  else
    echo false
  fi
}

main.bash

#! /bin/bash

nc='\e[0m'
yellow='\e[1;33m'
green='\e[1;32m'
red='\e[1;31m'
blue='\e[1;34m'


# Fail early in case of argumentation error
echo -e "${blue}- - - Initial Checks - - -${nc}"
source ./scripts/initial-checks-load-config.bash

输出对比

直接source时的正确输出

[2024-10-10 08:30:55] ERROR: This is an echoerr with echo -e

运行bash main.bash时的错误输出

- - - Initial Checks - - -
[2024-10-10 08:30:49] ERROR: This is an echoerr with echo -e
false

环境信息

  • 操作系统:Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-1015-azure x86_64)
  • Bash版本:GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)

问题原因

核心问题出在echoerr函数的输出定向逻辑上:

  • 直接source执行时,当前Shell环境没有定义red和nc变量,echo -ne $red和echo -ne $nc会输出空字符串到标准输出(stdout),此时first_check的stdout只有echo false的内容,x=$(first_check)得到纯净的false,do_check进入正确分支输出空行。
  • 运行bash main.bash时,main.bash定义了red和nc变量,echoerr里的echo -ne $red和echo -ne $nc会输出ANSI颜色转义序列到stdout(这两行没有重定向到stderr),导致x=$(first_check)得到的内容是「转义序列+false+转义序列」,[[ "$x" = 'false' ]]判断不成立,do_check进入else分支输出false。

解决方案

把echoerr函数里的所有输出都定向到stderr,避免颜色输出混入stdout干扰函数返回值:

echoerr() {
    {
        echo -ne $red
        echo "ERROR: $*" | ts '[%Y-%m-%d %H:%M:%S]'
        echo -ne $nc
    } 1>&2
}

或者单独给每一行加重定向:

echoerr() {
    echo -ne $red 1>&2
    echo "ERROR: $*" | ts '[%Y-%m-%d %H:%M:%S]' 1>&2
    echo -ne $nc 1>&2
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:28:09