对于多个命令,有类似于pipefail的东西,比如'try'语句,但在bash中 . 我想做这样的事情:
echo "trying stuff"
try {
command1
command2
command3
}
并且在任何时候,如果任何命令失败,则退出并回显该命令的错误 . 我不想做以下事情:
command1
if [ $? -ne 0 ]; then
echo "command1 borked it"
fi
command2
if [ $? -ne 0 ]; then
echo "command2 borked it"
fi
等等......或类似的东西:
pipefail -o
command1 "arg1" "arg2" | command2 "arg1" "arg2" | command3
因为我相信的每个命令的参数(如果我错了,纠正我)会相互干扰 . 这两种方法对我来说似乎非常啰嗦和讨厌,所以我在这里呼吁采用更有效的方法 .
13 回答
我个人更喜欢使用轻量级方法,如here;
用法示例:
另一种方法是简单地将命令与
&&
连接在一起,这样第一个失败就会阻止其余的执行:这不是您描述的用例的常见模式 . 一般情况下,命令应该负责打印失败,这样您就不必手动执行此操作(可能需要使用
-q
标记来消除错误,当您编辑它们以便在失败时大喊大叫,而不是将它们包含在其他内容中这样做 .另请注意,您无需执行以下操作:
你可以简单地说:
您可以编写一个为您启动和测试命令的函数 . 假设
command1
和command2
是已设置为命令的环境变量 .你是什么意思“退出并回应错误”?如果您的意思是希望脚本在任何命令失败后立即终止,那么就这样做
在脚本的开头(但在下面注意警告) . 不要打扰回显错误消息:让失败的命令处理它 . 换句话说,如果你这样做:
和command2失败,在向stderr打印错误消息时,似乎你已经实现了你想要的 . (除非我误解了你想要的东西!)
作为推论,您编写的任何命令都必须表现良好:它必须向stderr而不是stdout报告错误(问题中的示例代码将错误输出到stdout),并且当它失败时它必须以非零状态退出 .
但是,我不再认为这是一个好习惯 .
set -e
已经用不同版本的bash改变了它的语义,虽然它适用于一个简单的脚本,但是有很多边缘情况它基本上是不可用的 . (考虑一下这样的事情:set -e; foo() { false; echo should not print; } ; foo && echo ok
这里的语义有些合理,但是如果你将代码重构为依赖于选项设置提前终止的函数,你很容易被咬掉 . )IMO最好写:要么
我有一套脚本功能,我在我的Red Hat系统上广泛使用 . 他们使用
/etc/init.d/functions
中的系统函数来打印绿色[ OK ]
和红色[FAILED]
状态指示器 .如果要记录哪些命令失败,可以选择将
$LOG_STEPS
变量设置为日志文件名 .用法
输出
代码
对于它的 Value ,编写代码以检查每个命令是否成功的简短方法是:
它仍然很乏味,但至少它是可读的 .
而不是创建转轮功能或使用
set -e
,而是使用trap
:陷阱甚至可以访问触发它的命令的行号和命令行 . 变量是
$BASH_LINENO
和$BASH_COMMAND
.我在bash中开发了一个几乎完美无缺的try&catch实现,它允许你编写如下代码:
你甚至可以将try-catch块嵌入其中!
代码是我bash boilerplate/framework的一部分 . 它进一步扩展了try&catch的概念,例如带有回溯和异常的错误处理(以及其他一些不错的功能) .
这是负责try&catch的代码:
随意使用,分叉和贡献 - 它在GitHub .
很抱歉,我无法对第一个答案发表评论但您应该使用新实例来执行命令:cmd_output = $($ @)
对于偶然发现此主题的fish shell用户 .
设
foo
是一个没有"return"(echo)值的函数,但它像往常一样设置退出代码 .为避免在调用函数后检查
$status
,您可以执行以下操作:如果它太长而无法放在一条线上:
当我使用
ssh
时,我需要区分连接问题引起的问题和errexit
(set -e
)模式下远程命令的错误代码 . 我使用以下功能:以功能方式检查状态
用法:
产量