让bash将条件内的错误视为错误

时间:2014-12-22 19:13:52

标签: bash shell sh

我想编写一个强大的bash脚本,我使用set -e来确保脚本在出现问题时停止运行。它运作良好,但仍有一个洞:条件。如果我写if f; then .... fi并且函数f在执行某些命令时失败,则脚本将不会终止。因此,我需要检查f中的每个命令的返回码,以及所有子例程f递归调用的返回码。这很烦人。

有什么东西,例如bash中的一些标志或选项,即使在条件内也会失败。唯一的例外是直接在return内的f语句。如果f调用gg返回1,则仍将其视为错误,但g也称为条件,即if g; then ... fi ,然后允许在returng语句。等等。

3 个答案:

答案 0 :(得分:4)

简洁,不。

如果您希望shell在失败时退出,请不要测试f;只需运行它。 then子句中的代码应该只跟随f的调用,因为只有f成功才能执行它。

旧代码:

set -e
if f; then echo "f succeeded"; fi

新代码:

set -e
f
echo "f succeeded"

如果成功,你只会看到“f success”;如果失败,set -e确保脚本退出。

答案 1 :(得分:1)

你要求做的事情有点奇怪。我可以想象为什么你要问的两种可能性:

  1. 如果函数f的正文中出现任何问题,您希望脚本退出,即使函数本身仍然返回成功

  2. 您希望区分成功计算出合法假值的函数和失败的函数。

  3. 对于案例1 - 不要这样做。如果在f内出现任何问题,该函数应该绝对返回false(如果不退出整个脚本本身)。如果它返回false,那么你很好 - 请参阅@ JonathanLeffler的回答。

    对于案例2,您有效地试图让$?履行两项职责。它可以是错误指示符或布尔结果;它不可能两者兼而有之。

    如果你想让你的脚本在出现问题时退出,你可以让这个函数在发生这种情况时调用exit,这样调用者就不用担心这种情况。

    或者,您可以使函数echo计算布尔值而不是返回它,并保留$?表示成功/失败。这样的事情,也许是:

    f() {
       if that thing is true; then
         echo 1
       else
         echo 0
       fi
       if something went wrong; then
         return 1
       else
         return 0
       fi
    }
    result=$(f)   # we'll blow up and exit if f returns nonzero in `$?`
    if (( result )); then
       ...
    fi
    

答案 2 :(得分:1)

您必须区分f false f遇到错误。

传统上,假设和错误条件都以相同的方式发出信号:将$?设置为非零值。

一些命令确实做出了这样的区分。例如,如果找到模式,grep命令会将$?设置为0,如果不是1则设置为2,如果出现错误,则设置为grep (例如丢失的文件)。因此,对于grep ... case $? in 0) # ok ;; 1) # pattern not found ;; *) # error ;; esac 命令,您可以执行以下操作:

grep

但这是{{1}}特有的。没有普遍的约定来区分产生“错误”结果的命令和失败,并且在许多情况下没有这样的区别。

要执行您想要的操作,您必须定义错误的构成,然后确定每个命令可以执行如何检测错误条件。