在循环内部调用的函数中调用的陷阱不会被调用。如果直接在循环体内调用陷阱,则按预期方式工作。如果在循环外调用相同的函数,则会调用陷阱。
#!/bin/bash
function error_handler() #---------------------
{
echo "ERROR STATUS: $?"
echo "ERROR COMMAND: $BASH_COMMAND"
echo "ERROR STACK:"
caller
echo "---------- end of stack dump ----------"
exit 1
}
function func()
{
echo "..inside func( $1)"
if false
then
true
rv=0
else
false
rv=1
fi
echo "..returning from func( $1), rv=$rv"
return $rv
}
set -o errtrace -o errexit
trap error_handler ERR
for N in 1 2 ; do
echo -e "\nbegin loop $N"
if func $N
then
echo "result of func($N): success"
else
echo "result of func($N): failed"
fi
echo "loop $N is done"
false
done
func 1
func 2
上面的实际结果运行脚本:
begin loop 1
..inside func( 1)
..returning from func( 1), rv=1
result of func(1): failed
loop 1 is done
ERROR STATUS: 1
ERROR COMMAND: false
ERROR STACK:
41 ./a.sh
---------- end of stack dump ----------
但是我希望在程序结束时从false
内的func()
行捕获陷阱,而不是false
。
让我们在最后注释掉false
。结果是:
begin loop 1
..inside func( 1)
..returning from func( 1), rv=1
result of func(1): failed
loop 1 is done
begin loop 2
..inside func( 2)
..returning from func( 2), rv=1
result of func(2): failed
loop 2 is done
..inside func( 1)
ERROR STATUS: 1
ERROR COMMAND: false
ERROR STACK:
21 ./a.sh
---------- end of stack dump ----------
现在在func()
内部调用了陷阱,但没有在循环1中调用!循环1和循环2均完成而没有陷阱。函数返回后是func 1
,它调用了陷阱。为时已晚。
为什么?
答案 0 :(得分:2)
罪魁祸首不是循环,而是这里的if
语句:
if func $N
当您在func
语句的测试中使用if
时,ERR
陷阱将在测试的整个过程中被挂起。在func()
内部发生的错误不会触发ERR
陷阱,也不会在启用errexit
的情况下导致外壳退出。
如果失败的命令是紧随
ERR
或while
关键字之后的命令列表的一部分,则不执行until
陷阱,{{ 1}}语句,是在if
或&&
列表中执行的命令的一部分,但最后一个||
或&&
之后的命令除外,除了最后一个管道之外,或者使用||
反转命令的返回值。这些是!
(errexit
)选项所遵循的相同条件。