【问题标题】:How to exit bash function if error?如果出错,如何退出 bash 功能?
【发布时间】:2017-03-18 17:05:19
【问题描述】:

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

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

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

【问题讨论】:

  • 你可以看看this
  • gradle ... || return?
  • 每个人都假设gradle 在测试失败时将有非零退出。情况可能并非如此。我没有看到文档说 gradle 将在测试失败时返回非零。需要注意的是,该函数正在调用gradle 来测试某个操作系统。 gradle 本身不会失败,但它进行的测试可能不会通过。

标签: bash


【解决方案1】:

1.使用子shell ( .. )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),但如果你有更大的函数,它可能会变得很糟糕。

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

【讨论】:

  • 确保不要将build 与测试一起运行,因为它会停用set -e。所以if ! build; then... 甚至if [ build -ne 0 ]; then .. 都不会按预期工作。
  • 它也不能作为管道的一部分工作,例如build || echo "build failed"
  • 请注意,当在函数内部或将要获取源的脚本中使用时,return "${exit_status}" 通常比exit "${exit_status}" 更合适。 stackoverflow.com/questions/4419952/…
  • @ZombieDev 你有什么解释为什么会这样吗?我的意思是,这很奇怪,如果你调用一个带有set -e 子shell 的函数,如果你执行|| anything,它将被忽略
【解决方案2】:

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

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

【讨论】:

  • 这看起来是最干净的解决方案,因为在 ~/.bashrc 的函数中使用 set -e 会导致终端退出。
  • 是否需要反斜杠?我认为&& 后跟换行符的解析方式相同。也许它不是可移植的功能。
【解决方案3】:

我会让脚本更细化:

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

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

【讨论】:

    【解决方案4】:

    你可以这样做:

    # 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 )
    

    【讨论】:

      【解决方案5】:

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

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

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

      希望这会有所帮助:)

      【讨论】:

      • OP 希望presubmit 在执行git push 之前提前退出。这只是说明如何在presubmit 以非零退出状态退出时做一些额外的事情。
      猜你喜欢
      • 1970-01-01
      • 2021-01-30
      • 2021-01-11
      • 1970-01-01
      • 2023-01-28
      • 2019-05-19
      • 1970-01-01
      相关资源
      最近更新 更多