Linux陷入了&& amp;&

时间:2014-04-18 13:27:15

标签: linux bash error-handling bash-trap

使用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。

2 个答案:

答案 0 :(得分:6)

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

#!/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

答案 1 :(得分:1)

根据documentation for 4.2 (recent at the time of this answer)

  

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

解决此问题的一种方法是使用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中,尽管文档似乎没有提到为失败的子shell触发ERR。 (子shell通常不被认为是一个简单的命令,但文档也没有否认它。)子shell的退出状态是最后一行的退出状态,在这种情况下(x && y)是如果x失败,则退出状态,否则退出状态为y

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