子脚本触发主脚本异常退出?bash脚本异常问题排查
问题原因分析:source子脚本后主脚本提前退出
问题场景
主脚本main.sh内容:
#!/usr/bin/env bash set -eu DEBUG="N" source child.sh echo "Returned"
子脚本child.sh内容:
#!/usr/bin/env bash set -eu [ "$DEBUG" = "Y" ] && echo && echo "Finished.." && echo
当DEBUG="Y"时主脚本正常执行到echo "Returned";但DEBUG="N"时,主脚本直接退出,无法执行到最后一行。在子脚本末尾添加echo "" > /dev/null后,两种情况都正常。
核心原因:set -e的退出规则
你开启的set -eu中,-e选项的作用是:当shell执行的任何简单命令返回非0状态时,立即退出当前shell进程,除非该命令属于例外场景(比如是if/while的条件、是&&/||链中不是最后一个的命令等)。
当DEBUG="N"时,子脚本中的[ "$DEBUG" = "Y" ]返回非0,后续&&链的命令都不会执行,整个命令链的退出状态就是[命令的非0值。而这条命令链是子脚本的最后一条命令,不属于set -e的例外情况,因此set -e会触发当前shell(也就是主脚本所在的shell)直接退出,导致主脚本后续的echo "Returned"根本没机会执行。
当你在子脚本末尾添加echo "" > /dev/null时,这条命令是子脚本的最后一条命令,它的退出状态是0,set -e不会触发退出,主脚本就能继续执行后续代码。
解决方案
方案1:给条件命令链加兜底的|| true
修改子脚本中的命令,确保整个命令链的退出状态始终为0:
[ "$DEBUG" = "Y" ] && echo && echo "Finished.." && echo || true
|| true会在前面的条件不成立时执行,让整个命令链的退出状态保持为0,避免触发set -e。
方案2:临时关闭set -e执行条件命令
在子脚本中临时禁用-e选项,执行完目标命令后再恢复:
set +e [ "$DEBUG" = "Y" ] && echo && echo "Finished.." && echo set -e
方案3:保留你发现的空操作命令
在子脚本末尾添加一条始终返回0的命令,比如true(比echo "" > /dev/null更简洁):
[ "$DEBUG" = "Y" ] && echo && echo "Finished.." && echo true
内容的提问来源于stack exchange,提问作者Maestro
相关产品推荐
相关产品推荐

