遇到同样的问题后,我找到了解决方法。实际上 3 取决于您想要实现的目标。
首先对 OP 示例代码进行小幅重写,因为处理退出代码需要一些额外的工作:
#! /bin/bash
set -eEu
bad_command_extra() {
return 42
}
bad_command() {
bad_command_extra
echo "NO!!"
}
if bad_command; then echo "NOO!!"; else echo "errexit worked: $?"; fi
如果只需要让 errexit 工作,那么调用bad_command
. 诀窍是bad_command
在后台启动:
(bad_command) &
bc_pid=$!
if wait $bc_pid; then echo "NOO!!"; else echo "errexit worked: $?"; fi
如果您也想使用输出(类似于abc=$(bad_command)
),请照常将其捕获到临时文件中:
tmp_out=$(mktemp)
tmp_err=$(mktemp)
(bad_command >$tmp_out 2>$tmp_err) &
bc_pid=$!
if wait $bc_pid; then echo "NOO!!"; else echo "errexit worked: $?"; fi
cat $tmp_out $tmp_err
rm -f $tmp_out $tmp_err
最后,我在测试中发现该wait
命令返回 0 或 1,但不是bad_command
(bash 4.3.42) 的实际退出代码。这需要更多的工作:
tmp_out=$(mktemp)
tmp_err=$(mktemp)
tmp_exit=$(mktemp)
echo 0 > $tmp_exit
(
get_exit () {
echo $? > $tmp_exit
}
trap get_exit ERR
bad_command >$tmp_out 2>$tmp_err
) &
bc_pid=$!
bc_exit=$(cat $tmp_exit)
if wait $bc_pid
then echo "NOO!!"
else echo "errexit worked: $bc_exit"
fi
cat $tmp_out $tmp_err
rm -f $tmp_out $tmp_err $tmp_exit
出于某种奇怪的原因,if
在这种情况下,像以前一样放在一行让我退出代码 0 !