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

Posted

技术标签:

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

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

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

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

【问题讨论】:

tldp.org/LDP/abs/html/exit-status.html 你可以看看this gradle ... || return? 每个人都假设gradle 在测试失败时将有非零退出。情况可能并非如此。我没有看到文档说 gradle 将在测试失败时返回非零。需要注意的是,该函数正在调用gradle 来测试某个操作系统。 gradle 本身不会失败,但它进行的测试可能不会通过。 【参考方案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://***.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" 更合适。 ***.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 以非零退出状态退出时做一些额外的事情。

以上是关于如果出错,如何退出 bash 功能?的主要内容,如果未能解决你的问题,请参考以下文章

bash Shell 总结《二》

SetParent 装载的窗体 会保留在进程中 如果程序运行中出错,包括更新,查询.... 出错, 该如何卸载窗体

shell脚本怎么设置语句出错自动退出?(set -eset -o errexit)使用未初始化的变量自动退出?(set -uset -o nounset)(退出脚本)

linux shell 命令定义和使用数组出错

使用pecl安装php扩展时出错-bash: pecl: command not found

shell脚本怎么设置语句出错自动退出?(set -eset -o errexit)使用未初始化的变量自动退出?(set -uset -o nounset)(退出脚本)shell set