1

使用trap可能有助于编写最干净的 bash 脚本。但是我想知道是否存在解决方案以便在以下情况下捕获错误:

GNU bash,版本 4.2.45

案例确定

#!/bin/bash
trap 'echo OK i see error at line $LINENO;exit' ERR 
unknowncommand
echo "test KO should never reach me"

案例KO

#!/bin/bash
trap 'echo OK i see error at line $LINENO;exit' ERR
unknowncommand && echo "miss the trap"
echo "test KO should never reach me"
  • 不幸的是,我们到达最后一句好像&&使整个句子不是 ERR。
4

2 回答 2

6

您想要评估整个评估的退出状态,而不是尝试短路。一种方法是将整个事物包装在一个子外壳中。例如:

#!/bin/bash
trap 'echo "OK i see error at line $LINENO"; exit' ERR
(unknowncommand && echo "miss the trap")
echo "test KO should never reach me"

这按预期工作。结果如下所示:

$ /tmp/err.sh 
/tmp/err.sh: line 3: unknowncommand: command not found
OK i see error at line 3
于 2014-04-18T13:43:59.943 回答
1

根据4.2 的文档(在此答案时最近)

如果 sigspec 为 ERR,则只要简单命令具有非零退出状态,就会执行命令 arg,但须符合以下条件。如果失败的命令是紧跟在 until 或 while 关键字之后的命令列表的一部分、是在 if 或 elif 保留字之后的测试的一部分、在 && 或 || 中执行的命令的一部分,则不会执行 ERR 陷阱。列表,或者如果命令的返回状态正在使用 ! 反转。

解决此问题的一种方法是使用if语句来检查值$?而不是&&列表。

trap 'echo OK i see error at line $LINENO;exit' ERR
unknowncommand
if [ $? -eq 0 ]; then
    echo "miss the trap"
fi
echo "test KO should never reach me"

另一个似乎可行的方法是将命令包装在子shell中,尽管文档似乎没有提到ERR为失败的子shell而触发。(子shell 通常不被认为是一个简单的命令,但文档也不否认它。)子shell 的退出状态是最后一行的退出状态,在这种情况下 ( x && y) 是xif的退出状态它失败了,否则退出状态y

trap 'echo OK i see error at line $LINENO;exit' ERR
( unknowncommand && echo "miss the trap" )
echo "test KO should never reach me"
于 2014-04-18T14:22:20.780 回答