我想编写一个强大的bash脚本,我使用set -e
来确保脚本在出现问题时停止运行。它运作良好,但仍有一个洞:条件。如果我写if f; then .... fi
并且函数f
在执行某些命令时失败,则脚本将不会终止。因此,我需要检查f
中的每个命令的返回码,以及所有子例程f
递归调用的返回码。这很烦人。
有什么东西,例如bash中的一些标志或选项,即使在条件内也会失败。唯一的例外是直接在return
内的f
语句。如果f
调用g
而g
返回1,则仍将其视为错误,但g
也称为条件,即if g; then ... fi
,然后允许在return
内g
语句。等等。
答案 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)
你要求做的事情有点奇怪。我可以想象为什么你要问的两种可能性:
如果函数f
,的正文中出现任何问题,您希望脚本退出,即使函数本身仍然返回成功。
您希望区分成功计算出合法假值的函数和失败的函数。
对于案例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}}特有的。没有普遍的约定来区分产生“错误”结果的命令和失败,并且在许多情况下没有这样的区别。
要执行您想要的操作,您必须定义错误的构成,然后确定每个命令可以执行如何检测错误条件。