使用这个脚本:tstNounset.sh
#!/bin/bash
set -x
set -o nounset;set -u
echo `echo $str`
function FUNC1() { echo $str; };export -f FUNC1;bash -c FUNC1
function FUNC2() { set -u;echo $str; };export -f FUNC2;bash -c FUNC2
echo "A - should not reach here?"
echo $str
echo "B - doesn't reach here."
我想防止以全局方式达到“A”,而不需要检查每个变量。
也没有使用set -e
(因为我已经处理了大多数错误和解决方法,因为许多也只是警告)。
我想是否可以有某种方法来检测“未绑定变量”甚至发生在子shell/子进程中,所以我可以强制退出吗?
我无法让事情顺利进行如何让 bash 脚本对 _each_ 命令的错误执行特定操作?或者如何使用 Trap 命令触发错误还。我找到了这个老问题也。
答案1
子壳
子 shell 无法杀死整个脚本。在 的影响下set -u
,子 shell 无法告诉其父级“嘿,我希望你将此视为致命错误”。如果set -u
它在子 shell 中有效但在其父 shell 中无效,那么这甚至没有意义。子 shell 所能做的就是返回一个非零退出代码。您可以手动或通过 来处理父级中的退出代码set -e
。
(set -u; …; echo $undefined_variable)
# here $? is nonzero
ret=$?; if [ $ret -ne 0 ]; then exit $ret; fi
子流程
您在这里所做的不是子 shell:您正在启动另一个程序。另一个程序恰好是 bash,它也是执行当前脚本的解释器,但这是一个巧合。 bash 调用的程序中的设置绝对没有理由导致 bash 本身退出。
set +e
bash -c 'do something'
echo "A - should and does reach here"
这与您所写的没有什么不同perl -e 'use strict; print $barf'
— Perl 会死掉并返回非零状态,但这不会导致 bash 脚本退出(除了在 下set -e
)。set -e
如果您想在子进程返回非零返回代码时退出,请使用。
答案2
我的脚本编码错误,但可以修复:
看看第一条、第二条、第三条评论:
- 第一个需要陷阱错误
- 第二个错误,你要小心,不会被困住!不使用
if ! ...
将阻止使用 $? 获取返回值? - 第三,不要直接回显,使用中间变量,这样可以捕获错误
tstNounset.sh:
#!/bin/bash
trap 'ErrorHappened;exit 1' ERR #1st A TRAP ERR IS REQUIRED
set -x
set -o nounset;set -u
#echo `echo $str`
nRet=0;if strA="`echo $str`";then : ;else nRet=$?;echo "Err$nRet";fi #2rd errors that you take care wont be trapped! do not use `if ! ...` will prevent getting return value with $?
echo "0 - should not reach here?"
strA="`echo $str`";echo "$strA" #3nd DO NOT ECHO DIRECTLY, use a intermediary variable so the error can be cautch
echo "1 - should not reach here?"
function FUNC1() { echo $str; };export -f FUNC1;bash -c FUNC1
function FUNC2() { set -u;echo $str; };export -f FUNC2;bash -c FUNC2
echo "A - should not reach here?"
echo $str
echo "B - doesnt reach here."