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

lim*_*imp 4 bash exit-code

我有一个假的bash函数,如:

has_error() {
  true
  echo "Ok..."
  false
  echo "Shouldn't be here!"
}
Run Code Online (Sandbox Code Playgroud)

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

> has_error; echo $?
Ok...
1
Run Code Online (Sandbox Code Playgroud)

但实际发生了什么:

> has_error; echo $?
Ok...
Shouldn't be here!
0
Run Code Online (Sandbox Code Playgroud)

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

编辑:

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

che*_*ner 12

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

has_error () (    # "(", not "{"
  set -e
  true
  echo "Ok..."
  false
  echo "Shouldn't be here!"
)
Run Code Online (Sandbox Code Playgroud)


小智 5

@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"
Run Code Online (Sandbox Code Playgroud)

这将输出类似

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
Run Code Online (Sandbox Code Playgroud)