【发布时间】:2013-04-27 18:44:50
【问题描述】:
我有一个 bash 脚本,它对我的源代码运行三个检查,如果所有命令都成功,则 exit 0,如果其中任何一个失败,则 exit 1:
#!/bin/bash
test1 ./src/ --test-1=option
exit_1=$?
test2 ./src/ test-2-options
exit_2=$?
test3 ./src/ -t 3 -o options
exit_3=$?
# Exit with error if any of the above failed
[[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]]
exit $?
此代码有效,但感觉过于冗长和冗长。有什么办法可以让这变得更好吗?具体来说,我不满意:
- 必须运行命令,然后将退出代码分配给变量
- 必须使用
[[ ... ]],然后在下一行收集其退出代码以退出 - 必须明确地将变量与 0 进行比较,如
[[ $var -eq 0 ]],而不是将它们视为布尔值
理想情况下,最终结果应该是更具可读性的内容,例如:
exit_1=( test1 ./src/ --test-1=option )
exit_2=( test2 ./src/ test-2-options )
exit_3=( test3 ./src/ -t 3 -o options )
# Exit with error if any of the above failed
exit ( $exit_1 && $exit_2 && $exit_3 )
我考虑过的一些事情:
在一行中将错误代码放入变量中:
exit_1=$( test1 ./src/ --test-1=option )$?
exit_2=$( test2 ./src/ test-2-options )$?
exit_3=$( test3 ./src/ -t 3 -o options )$?
这行得通,并且缩短了一点,但我以前从未见过其他人使用它。这是明智/理智的事情吗?这有什么问题吗?
只是运行测试,然后 && 一起:
test1 ./src/ --test-1=option && \
test2 ./src/ test-2-options && \
test3 ./src/ -t 3 -o options
status=$?
这 不 起作用,因为 bash 短路。如果test1 失败,test2 和 test3 不会运行,我希望它们都运行。
使用|| exit检测错误并退出
[[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]] || exit 1
这节省了一行尴尬的退出代码和变量,但exit 1 的重要部分现在位于行尾,您可能会错过它。理想情况下,这样的事情会起作用:
exit [[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]]
当然,这不起作用,因为[[ 返回它的输出而不是回显它。
exit $( [[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]] ; echo $? )
确实有效,但仍然看起来像一个可怕的结块
没有明确处理作为布尔值的退出代码
[[ $exit_1 && $exit_2 && $exit_3 ]]
这并没有做你希望它做的事情。 && 将三个返回码存储在变量中的最简单方法是使用完整的$var -eq 0 && ...。肯定有更好的方法吗?
我知道 bash 不是一种很好的编程语言 - 如果你甚至可以这样称呼它 - 但有什么办法可以让这不那么尴尬吗?
【问题讨论】:
-
var=$(foo)$?方法很有趣,但会将您的测试调用置于不必要的子外壳中。 -
至少,如果
[[ ... && ... && ... ]]是脚本的最后一条语句,那么最后的exit $?是不必要的。 -
有谁知道如何将此应用于 docker-compose --exit-code-from 标志?它允许 docker compose 假设服务的退出代码。如果任何服务的退出代码为 1,我希望 docker compose 的退出代码为 1,否则为 0。
-
stackoverflow.com/questions/29568352/… 看起来这个答案可以工作。您只需在运行 compose 后列出所有容器并聚合它们的退出代码。当您看到第一个退出代码 1 时不会中止,这是您在使用 --exit-code-from 标志时看到的行为
标签: bash