如果出错,如何退出 bash 功能?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40429865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:22:15  来源:igfitidea点击:

How to exit bash function if error?

bash

提问by Xi Zhang

I am making a presubmit script. It looks like this:

我正在制作一个预提交脚本。它看起来像这样:

function presubmit() {
  gradle test android
  gradle test ios
  gradle test server
  git push origin master
}

I want the function to exit, if any of the tests fail so it won't push a bug to git. How?

如果任何测试失败,我希望该函数退出,这样它就不会将错误推送到 git。如何?

回答by Drew Chapin

The way I do it is to add && \after every command in the function (except the last one).

我这样做的方法是&& \在函数中的每个命令之后添加(最后一个除外)。

function presubmit() {
    gradle test android && \
    gradle test ios && \
    gradle test server && \
    git push origin master
}

回答by awinecki

1. Use subshell ( .. )with set -e; to make it more concise, you can do this:

1.使用子shell( .. )set -e; 为了使它更简洁,你可以这样做:

build() {( set -e        # Fail early
  build_cmd_step_1
  build_cmd_step_2
  build_cmd_step_3
  ...
)}

Then, the function will fail on the first failure and you can intercept the exit status:

然后,该函数将在第一次失败时失败,您可以拦截退出状态:

build
exit_status=$?
if [ ${exit_status} -ne 0 ]; then
  echo "We have error - build failed!"
  exit "${exit_status}"
fi

2. Alternatively, the && \chaining inside a functionis also good (https://stackoverflow.com/a/51913013/1375784), though it might get bad if you have a bigger function.

2. 或者,&& \函数内部的链接也很好(https://stackoverflow.com/a/51913013/1375784),但如果你有更大的函数可能会变坏。

Both methods can be good, depending on your use case (in some cases using subshells may cause some unwanted side effects)

这两种方法都可以,这取决于您的用例(在某些情况下使用子外壳可能会导致一些不需要的副作用)

回答by anubhava

You can do this:

你可以这样做:

# declare a wrapper function for gradle
gradle() {
   command gradle "$@" || exit 1
}

presubmit() {
  gradle test android
  gradle test ios
  gradle test server
  git push origin master
}

declare -xf presubmit gradle

Call the function in a subshell as:

在子shell中调用函数:

( presubmit )

回答by Kostanos

I would make script more granulated:

我会让脚本更加细化:

#!/bin/bash

function test() {
  gradle test android
  gradle test ios
  gradle test server
}
function push() {
  git push origin master
}
# this subshell runs similar to try/catch
(
  # this flag will make to exit from current subshell on any error inside test or push
  set -e
  test
  push
)
# you catch errors with this if
if [ $? -ne 0 ]; then
  echo "We have error"
  exit $?
fi

We track error only inside test and push. You can add more actions outside of subshell where test and push run. You can also this way add different scope for errors (let consider it as try/catch)

我们只在测试和推送中跟踪错误。您可以在测试和推送运行的子外壳之外添加更多操作。您也可以通过这种方式为错误添加不同的范围(让我们将其视为 try/catch)

回答by MichaelMMeskhi

Usually when I call a function and want an error message incase it fails I do this:

通常当我调用一个函数并想要一个错误消息,以防它失败,我这样做:

presubmit || { echo 'presubmit failed' ; exit 1; }

presubmit || { echo 'presubmit failed' ; exit 1; }

By adding the ||flag, it will determine whether which expression is TRUE.

通过添加||标志,它将确定哪个表达式是否为 TRUE。

Hope this helps :)

希望这可以帮助 :)

回答by Moinuddin Quadri

Use the builtin set -e:

使用内置set -e

#!/bin/bash
set -e
# Any subsequent commands which fail will cause the shell script to exit immediately

Text from set -edocument:

set -e文档中的文本:

-e: Exit immediately if a pipeline, which may consist of a single simple command, a list, or a compound commandreturns a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return status is being inverted with !. If a compound command other than a subshell returns a non-zero status because a command failed while -e was being ignored, the shell does not exit. A trap on ERR, if set, is executed before the shell exits.

This option applies to the shell environment and each subshell environment separately (see Command Execution Environment), and may cause subshells to exit before executing all the commands in the subshell.

If a compound command or shell function executes in a context where -e is being ignored, none of the commands executed within the compound command or function body will be affected by the -e setting, even if -e is set and a command returns a failure status. If a compound command or shell function sets -e while executing in a context where -e is ignored, that setting will not have any effect until the compound command or the command containing the function call completes.

-e:如果管道(可能由单个简单命令列表复合命令组成)返回非零状态,则立即退出。如果失败的命令是紧跟在 while 或 until 关键字之后的命令列表的一部分、if 语句中测试的一部分、在 && 或 || 中执行的任何命令的一部分,则 shell 不会退出 列表除了最后一个 && 或 || 之后的命令,管道中除最后一个之外的任何命令,或者如果命令的返回状态正在用 ! 反转。如果子shell 以外的复合命令由于命令在-e 被忽略时失败而返回非零状态,则shell 不会退出。如果设置了 ERR 上的陷阱,则会在 shell 退出之前执行。

该选项分别适用于shell环境和每个子shell环境(参见命令执行环境),并且可能导致子shell在执行子shell中的所有命令之前退出。

如果复合命令或 shell 函数在 -e 被忽略的上下文中执行,则复合命令或函数体内执行的任何命令都不会受到 -e 设置的影响,即使设置了 -e 并且命令返回故障状态。如果复合命令或 shell 函数在忽略 -e 的上下文中执行时设置了 -e,则在复合命令或包含函数调用的命令完成之前,该设置不会产生任何影响。