繁体   English   中英

Bash 函数忽略 set -e

[英]Bash functions ignore set -e

如何将 function 作为“测试命令”运行并对失败执行操作,同时在发生错误时仍中止 function? 考虑以下脚本

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

我得到的 output 是

Entering foo
Should not reach this line
Entering foo

虽然我想得到

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

我想我正在寻找一种将 function 标记为未经测试的命令的方法。 根据 bash 手册页

 -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.

编辑预期的 output 是错误的。 为清楚起见对其进行了编辑

set -e在第一次调用foo被禁用,因为它位于||的左侧

另外,您永远也不会看到I want to see this ...输出的I want to see this ...字符串,除非foo的最后一个echo以某种方式失败了(这是foo中的最后一个echo决定了函数的退出状态)。

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

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

上面的输出(带或不带set -x

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

现在falsefoo最后执行的语句。

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

#!/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 +eset -e用于抑制错误失败,否则脚本将在第一个错误时退出
  • trap用于中止任何错误(而不是set -e()用于在子shell中运行给定代码),因此外部脚本将在失败后继续运行,而set -E用于将trap传递给子壳。 因此(set -E ; trap 'exit 1' ERR ; eval $1)在没有退出整个脚本的情况下,在第一个错误时运行给定的代码/函数中止
  • $? -ne 0 $? -ne 0检查失败,并且eval $2运行错误处理代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM