如何在set -e上下文中运行flakey命令?

时间:2018-03-03 20:00:41

标签: bash error-handling

我想用set -e保护我的大多数bash脚本,以便在脚本处理过程中检测到错误时提前和大声失败。但是,我仍然希望能够运行一些实际上预期会失败的命令,例如使用grep来评估某些文件内容的存在/不存在,这些文件内容用于指示其余部分的控制流。脚本。如何在grep上下文中运行set -e,以便允许A)grep失败并且B)grep的存在状态被记录以供脚本的其余部分访问?

在普通的POSIX中,我会做类似的事情:

grep 'needle' haystack >/dev/null
if [ "$?" -eq 0 ]; then
    handle_grep_results
else
    handle_grep_no_results
fi

但是,在本节之前指定set -e时,只要grep找不到针,脚本就会提前退出。解决此问题的一种方法是暂时禁用set +e的保护,然后在该部分后重新启用它们,但如果有意义,我宁愿保留保护。这可能与bash一起使用吗?

2 个答案:

答案 0 :(得分:1)

您只需查看grep的返回状态:

即可
grep -q luck myfile.txt || no_luck=1

Shell实用程序使用返回状态与shell通信;他们正在沟通的不一定是错误的条件。正如grep示例所示,它可以是一个简单的布尔值。实际上,[[内置(及其朋友[test)正是这样做的:使用状态代码返回布尔结果。这并没有使这些工具变得“松懈”。

set -e忽略在||&&连接器的条件或左侧执行的命令的非零状态返回,这使得可以使用{{ 1}}。

话虽如此,set -e是一个非常生硬的工具,通常不建议在生产代码中使用它。您始终可以使用-e明确失败:

||

答案 1 :(得分:1)

您的if命令似乎包含一些拼写错误(#之前的额外]和遗漏空间),但更一般地说,您应该了解非常 if的目的是运行命令并检查其退出代码。任何看起来像

的东西
command
if [ $? = 0 ]; then

更紧凑,更具惯用性

if command; then

并且在此上下文中,command的失败退出状态不是导致set -e终止脚本的条件(因为那时脚本中没有else子句set -e!)

在这个thenelse块都包含简单命令的特定示例中,您可以简化为简写

grep -q 'needle' haystack && handle_grep_results || handle_grep_no_results

也暗示

command || true

如果您只是不关心commandset -e的脚本中是否成功。

(另请注意grep -q超过grep >/dev/null - 前者暗示-m 1,即grep可以关闭文件,并在找到后立即返回成功匹配。)