在Bash脚本中引发错误

我想在消息“测试用例失败!!!”的Bash脚本中引发错误。 如何在Bash中做到这一点?

例如:

if [ condition ]; then
    raise error "Test cases failed !!!"
fi

这取决于您想要存储错误消息的位置。

您可以执行以下操作:

echo "Error!" > logfile.log
exit 125

或者以下:

echo "Error!" 1>&2
exit 64

当你引发异常时,你停止程序的执行。

您也可以使用类似exit xxx地方,其中xxx是您可能想要返回到操作系统的错误代码(从0到255)。 这里12564只是随机代码,你可以退出。 当您需要向操作系统表明程序异常停止(例如发生错误)时,您需要传递非零退出代码以exit

正如@chepner指出的那样,你可以做exit 1 ,这意味着一个未明确的错误。


基本的错误处理

如果你的测试用例运行者为失败的测试返回一个非零代码,你可以简单地写出:

test_handler test_case_x; test_result=$?
if ((test_result != 0)); then
  printf '%sn' "Test case x failed" >&2  # write error message to stderr
  exit 1                                  # or exit $test_result
fi

甚至更短:

if ! test_handler test_case_x; then
  printf '%sn' "Test case x failed" >&2
  exit 1
fi

或者最短的:

test_handler test_case_x || { printf '%sn' "Test case x failed" >&2; exit 1; }

用test_handler的退出码退出:

test_handler test_case_x || { ec=$?; printf '%sn' "Test case x failed" >&2; exit $ec; }

高级错误处理

如果你想采取更全面的方法,你可以有一个错误处理程序:

exit_if_error() {
  local exit_code=$1
  shift
  [[ $exit_code ]] &&               # do nothing if no error code passed
    ((exit_code != 0)) && {         # do nothing if error code is 0
      printf 'ERROR: %sn' "$@" >&2 # we can use better logging here
      exit "$exit_code"             # we could also check to make sure
                                    # error code is numeric when passed
    }
}

然后在运行测试用例后调用它:

run_test_case test_case_x
exit_if_error $? "Test case x failed"

要么

run_test_case test_case_x || exit_if_error $? "Test case x failed"

具有像exit_if_error这样的错误处理程序的exit_if_error是:

  • 我们可以在一个地方将所有的错误处理逻辑标准化,如记录日志,打印堆栈跟踪,通知,清理等
  • 通过使错误处理程序,出现错误代码作为参数,我们可以从杂乱的备用调用者if块的错误,测试退出码
  • 如果我们有一个信号处理程序(使用陷阱),我们可以从那里调用错误处理程序
  • 相关文章

  • 在Bash中处理错误
  • Linux中是否有标准退出状态码?
  • BashFAQ / 105 - 为什么不设置-e(或设置-o errexit,或陷阱ERR)做我的预期?
  • 在Bash中__FILE____FILE__ __LINE__等效
  • 在Bash中是否有TRY CATCH命令?
  • 要将堆栈跟踪添加到错误处理程序中,您可能需要查看此帖子:由Bash脚本调用的已执行程序的跟踪
  • 忽略shell脚本中的特定错误
  • 如何在shell脚本中管理日志冗长?
  • 如何在Bash中记录函数名和行号?
  • 双方括号[[]]优于Bash中的单方括号[]吗?

  • 有几种方法可以解决这个问题。 假设您的一项要求是运行包含几个shell命令的shell脚本/函数,并检查脚本是否成功运行,并在出现故障时抛出错误。

    shell命令通常依赖返回的退出代码来让shell知道它是成功的还是因某些意外事件而失败。

    所以你想要做的是落在这两个类别上

  • 错误退出
  • 出错并清理出错
  • 根据您想要执行的操作,可以使用shell选项。 对于第一种情况,shell提供了set -e选项,第二种情况下,您可以在EXIT上执行trap

    我应该在脚本/函数中使用exit吗?

    使用exit通常会增强可读性在某些例程中,一旦知道了答案,就要立即退出到调用例程。 如果例程定义为一旦检测到错误时不需要进一步清理,则不立即退出意味着您必须编写更多代码。

    因此,如果您需要对脚本执行清理操作以使脚本终止清理,则最好不要使用exit

    我是否应该使用set -e来退出时出错?

    没有!

    set -e是尝试向shell中添加“自动错误检测”。 它的目标是让shell在发生错误时中止,但它带有很多潜在的陷阱,例如,

  • 作为if测试的一部分的命令是免疫的。 在这个例子中,如果你期望在不存在的目录上进行test检查,它不会,它会转到else条件

    set -e
    f() { test -d nosuchdir && echo no dir; }
    f
    echo survived
    
  • 除了最后一个管道以外的命令都是免疫的。 在下面的例子中,因为最近执行的(最右边的)命令的退出代码被认为是( cat )并且它是成功的。 这可以通过set -o pipefail选项来避免,但它仍然是一个警告。

    set -e
    somecommand that fails | cat -
    echo survived 
    
  • 建议使用 - 出口trap

    判断是,如果你想能够处理一个错误而不是盲目退出,而不是使用set -e ,那么在ERR伪信号上使用一个trap

    当shell本身以非零错误代码退出时, ERR陷阱不会运行代码,但当该shell运行的任何命令不是条件的一部分(如if cmdcmd || )时,都会退出非零退出状态。

    通常的做法是我们定义一个陷阱处理程序,以提供有关哪条线路以及导致退出的附加调试信息。 请记住导致ERR信号的最后一条命令的退出代码在此时仍然可用。

    cleanup() {
        exitcode=$?
        printf 'error condition hitn' 1>&2
        printf 'exit code returned: %sn' "$exitcode"
        printf 'the command executing at the time of the error was: %sn' "$BASH_COMMAND"
        printf 'command present on line: %d' "${BASH_LINENO[0]}"
        # Some more clean up code can be added here before exiting
        exit $exitcode
    }
    

    我们只是在失败的脚本的顶部使用这个处理程序

    trap cleanup ERR
    

    把它放在一个简单的脚本上,它包含了第15行的false信息,这些信息就是你所得到的

    error condition hit
    exit code returned: 1
    the command executing at the time of the error was: false
    command present on line: 15
    

    trap还提供了选项,不管错误如何,只要在shell完成时运行清理(例如,你的shell脚本退出),在信号EXIT 。 您也可以同时捕获多个信号。 可以在trap.1p - Linux手册页上找到要陷入的支持信号列表

    另一件需要注意的事情是要明白,如果您正在处理子shell,则所提供的方法都不起作用,在这种情况下,您可能需要添加自己的错误处理。

  • set -e的子shell上不起作用。 false仅限于子shell,并且永远不会传播到父shell。 要在这里执行错误处理,请添加您自己的逻辑来执行(false) || false (false) || false

    set -e
    (false)
    echo survived
    
  • trap也一样。 由于上述原因,下面的逻辑将不起作用。

    trap 'echo error' ERR
    (false)
    
  • 链接地址: http://www.djcxy.com/p/97037.html

    上一篇: Raise error in a Bash script

    下一篇: How to find whether or not a variable is empty in Bash script