我在一个全新的Ubuntu 14.04.2上有一个名为test.sh
的脚本,它可以做到这一点:
#!/bin/sh
set -o errexit
# Start by building the box
docker build -t dcyclebox-test .
# Test nginx
docker run dcyclebox-test bash -c 'nginx -v' && echo '[test] nginx works'
echo '[status] end of test script'
nginx命令不存在,所以我希望我在脚本开头设置set -o errexit
以使整个脚本返回非零错误代码,但脚本始终返回0:< / p>
$ test.sh
...
bash: nginx: command not found
[status] end of test script
$ echo $?
0
似乎set -o errexit
什么都不做。如果我删除了最后一行,即echo '[status] end of test script'
,该脚本将按预期返回非零退出代码:
$ test.sh
...
bash: nginx: command not found
$ echo $?
127
但是如果任何的行失败,我希望脚本失败,而不仅仅是最后一行。我现在唯一能做的就是在每一行的末尾添加&&\
,如下所示:
#!/bin/sh
# Start by building the box
docker build -t dcyclebox-test . &&\
# Test nginx
docker run dcyclebox-test bash -c 'nginx -v' && echo '[test] nginx works' &&\
echo '[status] end of test script'
现在,如果nginx不存在,运行脚本将失败(这很好)(请注意我删除了set -o errexit
,因为它似乎没有做任何事情。)
$ test.sh
...
bash: nginx: command not found
$ echo $?
127
所以我的问题是我可以在脚本顶部添加什么命令,如果其中的任何命令以非零代码退出,则告诉它退出?
谢谢!
答案 0 :(得分:5)
由于你的shebang #!/bin/sh
和sh
在Ubuntu上符号链接到dash
,dash
的规则会管理你脚本的执行。
关于set -e
及其等价物,set -o errexit
,man dash
州(强调我的):
-e errexit如果不是交互式,如果任何未经测试的命令失败,请立即退出。命令的退出状态被认为是显式的 如果命令用于控制if,elif,while或者直到;或者如果命令是“&amp;&amp;”的左手操作数或 “||”运算符。
根据此定义,您的命令的LHS(左侧)
docker run dcyclebox-test bash -c 'nginx -v' && echo '[test] nginx works'
是一个显式测试的命令,因此在LHS命令失败的情况下自动终止不启动。
您可以通过简单地echo '[test] nginx works
单独的命令(显然您也可以将其置于新行)来解决此问题:
docker run dcyclebox-test bash -c 'nginx -v'; echo '[test] nginx works'
现在,如果docker run dcyclebox-test bash -c 'nginx -v'
失败(返回非零退出代码),脚本会立即终止(报告退出代码)。
答案 1 :(得分:1)
从手册页:
如果管道(可能包含单个简单命令),列表或复合命令(请参阅上面的SHELL GRAMMAR),则立即退出,并以非零状态退出。 如果失败的命令是紧跟在while或until关键字之后的命令列表的一部分,那么shell不会退出,在if或elif保留字之后的部分测试,在&amp;中执行的任何命令的一部分;&amp; 或||列表除了 final&amp;&amp;&amp; 或||之外的命令,管道中的任何命令但最后一个命令,或者命令的返回值是否被反转!。如果子shell以外的复合命令返回非零状态,因为在忽略-e时命令失败,则shell不会退出。 ERR上的陷阱(如果已设置)将在shell退出之前执行。此选项分别适用于shell环境和每个子shell环境(请参阅上面的COMMAND EXECUTION ENVIRONMENT),并且可能导致子shell在执行子shell中的所有命令之前退出。