本文介绍了Bash函数忽略set -e的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将功能作为经过测试的命令"运行并在失败时执行操作,同时在发生错误时仍中止功能?考虑以下脚本

How can I run a function as a "tested command" and perform action on failure, while still aborting the function as soon as an error occur?Consider the following script

#!/bin/bash -e

function foo() {
   echo Entering foo
   false
   echo Should not reach this line
}

foo || echo I want to see this line on failure in foo
foo

我得到的输出是

Entering foo
Should not reach this line
Entering foo

我想得到

Entering foo
I want to see this line on failure in foo
Entering foo

我猜我正在寻找一种将功能标记为未经测试的命令的方法.根据bash手册页

I guess what I'm looking for is a way to mark the function as untested command. According bash man page

 -e errexit
         Exit immediately if any untested command fails in non-interactive
         mode.  The exit status of a command is considered to be explicitly
         tested if the command is part of the list used to control an if,
         elif, while, or until; if the command is the left hand operand of
         an "&&" or "||" operator; or if the command is a pipeline preceded
         by the ! operator.  If a shell function is executed and its exit
         status is explicitly tested, all commands of the function are con‐
         sidered to be tested as well.

编辑预期的输出是错误的.为了清晰起见对其进行了编辑

EDITThe expected output was wrong. edited it for clarity

推荐答案

我最终将代码包装到了下面的实用程序函数中.

I ended up wrapping the code to do so in a utility function below.

#!/bin/bash -e

# Runs given code aborting on first error and taking desired action on failure
# $1 code to invoke, can be expression or function name
# $2 error handling code, can be function name or expressions
function saferun {
  set +e
  (set -E ; trap 'exit 1' ERR ; eval $1)
  [ $? -ne 0 ] && eval $2
  set -e
}

function foo() {
   echo Entering foo
   false
   echo Should not reach this line
}

saferun foo "echo I want to see this line on failure in foo"
foo

让我们分解一下:

  • set + e set -e 用于抑制错误失败,否则脚本将在出现第一个错误时退出
  • trap 用于在发生任何错误时终止执行(而不是 set -e )()用于运行给定的代码在subshel​​l中,因此外部脚本在失败后将继续运行,并且使用 set -E 将陷阱传递到subshel​​l中.因此(set -E; trap'exit 1'ERR; eval $ 1)在第一次错误时运行给定的代码/函数中止,而没有退出整个脚本
  • $?-ne 0 检查是否失败,并且 eval $ 2 运行错误处理代码
  • set +e and set -e are used to suppress failure on error, as otherwise the script will just exit on first error
  • trap is used to abort the execution on any error (instead of set -e) () is used to run the given code in subshell, so outer script will keep running after failure, and set -E is used to pass the trap into the subshell. so (set -E ; trap 'exit 1' ERR ; eval $1) run the given code / function aborting on first error while not exiting the whole script
  • $? -ne 0 check for failures and eval $2 runs the error handling code

这篇关于Bash函数忽略set -e的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 07:39