如何使 bash 函数在任何错误时返回 1

Posted

技术标签:

【中文标题】如何使 bash 函数在任何错误时返回 1【英文标题】:How to make a bash function return 1 on any error 【发布时间】:2015-05-27 16:53:51 【问题描述】:

我有一个像这样的假 bash 函数:

has_error() 
  true
  echo "Ok..."
  false
  echo "Shouldn't be here!"

当我运行这个函数并检查错误状态时,我希望发生什么:

> has_error; echo $?
Ok...
1

但实际发生了什么:

> has_error; echo $?
Ok...
Shouldn't be here!
0

问题是函数在抛出错误后继续执行,而且我什至无法检测到抛出错误。我怎样才能改变这个?我可以在函数的开头放一个set -e,但是如果抛出错误,我的整个shell 将终止。我想要的是简单地让它返回并将退出状态设置为1。我可以在命令之间放置&&,或者在每一行加上|| return 1后缀,但这些都不是很优雅.这样做的正确方法是什么?

编辑:

似乎我不够清楚,因为很多回复似乎表明我实际上并不知道如何在 bash 中执行测试。正如我上面提到的,我知道我可以手动测试函数中的每个命令,并根据需要返回或处理错误。我也知道我可以set -e 并导致我的 shell 会话因错误而终止。但我要问的是:如果该函数中的任何命令返回非零状态,有没有办法让函数停止继续执行——无需明确测试?

【问题讨论】:

Use a trap 或许? set -e 将在发生错误时终止。不确定它适用的范围,但总是值得知道这一点。 @RedX 我在帖子中提到了这一点,以及它在这里不起作用的原因。 在使用set -e之前,您可能需要查看:Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected? 【参考方案1】:

如果您的函数不需要设置任何全局变量,您可以让函数创建一个使用set -e 的子shell。子shell 将退出,而不是调用has_error 的shell。

has_error () (    # "(", not ""
  set -e
  true
  echo "Ok..."
  false
  echo "Shouldn't be here!"
)

【讨论】:

我认为这是正确的解决方案(对我有用)... OP,考虑接受吗? 优秀的解决方案!但是,如果我执行 has_error || echo "I failed" 函数怎么会像 set -e 从未完成一样执行?【参考方案2】:

@chepner 的回答对我有帮助,但不完整。

如果要查看函数返回码,请不要将函数调用放在if 语句中,使用$? 变量。

randomly_fail() (
  set -e
  echo "Ok..."
  (( $RANDOM % 2 == 0 ))
  echo "I'm lucky"
)

FAILED=0
SUCCESS=0
for (( i = 0; i < 10; i++ )); do
  randomly_fail
  if (( $? != 0 )); then
      (( FAILED += 1 ))
  else
    (( SUCCESS += 1 ))
  fi
done

echo "$SUCCESS success, $FAILED failed"

这将输出类似

Ok...
I'm lucky
Ok...
I'm lucky
Ok...
I'm lucky
Ok...
Ok...
I'm lucky
Ok...
Ok...
I'm lucky
Ok...
Ok...
Ok...
I'm lucky
6 success, 4 failed

【讨论】:

+1 澄清代码的好答案 - 退出代码 $?被捕获是因为 () 之间的代码实际上是在一个新的分叉 shell 进程中执行的...

以上是关于如何使 bash 函数在任何错误时返回 1的主要内容,如果未能解决你的问题,请参考以下文章

在Dart / IntelliJ Idea中如何在错过退货时将其设为错误?

遇到错误时如何使批处理文件终止?

当任何数学运算产生“NaN”时,如何强制 C# 编译器抛出异常?

如果搜索参数为空白或缺失/错误,我如何使用 Xpath 函数“contains()”不返回任何内容?

如果一个函数有错误的参数,如何防止它返回任何值?

如何在 Visual Studio 2012 中使一个类完全静态,这样它就不会出现任何错误? - C# [关闭]