我目前正在使用这样的东西:
(
false
true
) && echo "OK" || echo "FAILED";
但它不起作用。如果出现故障(在这种情况下为false),我希望子shell退出并返回一个错误。目前,只有当最后一个命令失败时,它才会失败。
它应该只退出当前的子shell,而不是整个脚本。
我把这个脚本交给了人们,我不想让他们看到所有的输出,但如果脚本成功与否,我仍然会给他们一些回应。
编辑:上面子shell中的命令只是一个例子。我想在子shell中运行多个命令,而不检查每个命令后的返回值。类似于潜艇外壳的set-e。
第二版:我试着在一个subshell中添加set-e。也许我做错了什么,但这并没有改变我剧本的行为。它没有停止执行,也没有使用非0代码退出子shell。
(
set -e
false
echo "test"
) && echo "OK" || echo "FAILED";
首先打印测试,然后打印OK。由于错误,它应该打印FAILED。
bashset -e
在类似foo || true
的条件表达式中的这种影响是已知的,并且被认为是一个问题。我认为这是讨厌set -e
和shell脚本的好理由。
- http://david.rothlis.net/shell-set-e/
- http://fvue.nl/wiki/Bash:_Error_handling
第一个链接提出以下建议。它在小例子中看起来不错,但在现实世界中可能不太清楚。
将一系列命令串在一起,进行自己的错误检查像这样用"&&":
mkdir abc && cd abc && do_something_else && last_thing || { echo error >&2; exit 1; }
几个重要的注意事项:您不需要尾部的反斜杠。你没有缩进下一行。你必须坚持每行80个字符,这样每个人都可以看到末尾的"&&"或"||"。如果需要混合AND和OR,用{这些大括号}分组,它们不会产生子外壳。
对于您编辑的问题:
类似于子shell的set-e。
好吧,您可以为子shell执行set -e
。
( set -e
my
commands
)
您不能隐式地使仅您的子shell具有errexit
选项。您可以使用eval
进行一些欺骗,或者使用子流程作为shell(即使子流程与子shell不同),如
errexit_shell() {
bash -e
}
但由于各种原因,这些选项都是不可取的,尤其是可读性。在这种情况下,最好的办法就是调整整个脚本以使用set -e
,然后您的子shell就会出现。
对于您最初的问题:
只需捕捉表示成功或失败的部件的状态:
(
cat teisatrt
status=$?
echo "true"
exit "$status"
) && echo passed || echo failed
(当然,如果您只想知道该文件是否可读,请不要对其进行cat操作,只需使用test -r
即可。)
正如您所拥有的,您正在将整个子shell的输出重定向到/dev/null,因此您永远不会看到您的"true"回波。您应该将子shell中的重定向移动到您真正想要的命令。为了在cat
失败时退出子shell,您需要在cat
运行后检查是否失败。如果您不这样做,那么正如您所指出的,它的返回代码将被下面的语句擦除。这样的东西:
echo "Installing App"
(
cat teisatrt &> /dev/null || exit 1
echo "true"
) && echo "OK" || echo "FAILED";