如果出错,如何退出bash函数?

时间:2016-11-04 18:48:39

标签: bash

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

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

我希望函数退出,如果任何测试失败,那么它不会将bug推送到git。怎么样?

6 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

使用内置set -e

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

来自set -e文档的文字:

  

-e :如果pipeline可能包含simple commandlist或a compound command返回非零状态。如果失败的命令是紧跟在while或until关键字之后的命令列表的一部分,if语句中的测试的一部分,在&&amp ;;中执行的任何命令的一部分,则shell不会退出。或||列表除了最后一个&&之后的命令或者||,管道中的任何命令,但是最后一个,或者命令的返回状态是否被反转!如果子shell以外的复合命令返回非零状态,因为在忽略-e时命令失败,则shell不会退出。 ERR上的陷阱(如果已设置)将在shell退出之前执行。

     

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

     

如果复合命令或shell函数在忽略-e的上下文中执行,则复合命令或函数体中执行的任何命令都不会受-e设置的影响,即使设置了-e且a命令返回失败状态。如果复合命令或shell函数在忽略-e的上下文中执行时设置-e,则在使用复合命令或包含函数调用的命令完成之前,该设置将不起作用。

答案 2 :(得分:1)

通常当我调用一个函数并想要一个错误消息时,如果它失败了我就这样做:

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

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

希望这会有所帮助:)

答案 3 :(得分:1)

你可以这样做:

# 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

在子shell中调用该函数:

( presubmit )

答案 4 :(得分:1)

我会让脚本更加颗粒化:

#!/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

我们仅在测试和推送内跟踪错误。您可以在子shell外添加更多操作,其中test和push run。您也可以通过这种方式为错误添加不同的范围(让我们将其视为try / catch)

答案 5 :(得分:1)

1。将子外壳( .. )set -e 一起使用;为了更加简洁,您可以执行以下操作:

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

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

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

2。另外,功能内的&& \链接也很好(https://stackoverflow.com/a/51913013/1375784),尽管如果您有更大的功能,链接可能会变坏。

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