Bash脚本:如何确保脚本在使用";调用的函数中出现任何错误时退出;或;(| |)条件?

Bash脚本:如何确保脚本在使用";调用的函数中出现任何错误时退出;或;(| |)条件?,bash,shell,error-handling,exit-code,Bash,Shell,Error Handling,Exit Code,下面是一个示例脚本: #!/bin/bash set -euo pipefail function_test () { echo "Everything still ok." thisdoesnotexist echo "It continues running..." } function_test || { echo "Error occured in function_test."; exit 1; } 我希望这个脚本在“thisdoe

下面是一个示例脚本:

#!/bin/bash
set -euo pipefail

function_test () {
        echo "Everything still ok."
        thisdoesnotexist
        echo "It continues running..."
}

function_test || { echo "Error occured in function_test."; exit 1; }
我希望这个脚本在“thisdoesnotexist”上退出,因为set-e被激活了。应该出现错误消息“函数测试中出错”,或者至少应该退出脚本。相反,脚本会继续运行:

$ ./testscript.sh 
Everything still ok.
./testscript.sh: Zeile 6: thisdoesnotexist: Kommando nicht gefunden.
It continues running...
我想这是因为根据
set
手册,我在“或”(| |)上下文中使用该函数:

立即退出[…],除非失败的命令是 直到或while循环、if语句的一部分、&&or语句的一部分|| 清单,[…]

在脚本中处理此问题的最佳方法是什么?我删除了“| |”并使用了如下错误陷阱:

#!/bin/bash
set -Eeuo pipefail

errorhandler () {
        echo "Errorhandler called. Exiting."
        exit 1
}

trap "errorhandler" ERR

function_test () {
        echo "Everything still ok."
        thisdoesnotexist
        echo "It continues running..."
}

function_test
哪种方法有效:

$ ./testscript.sh 
Everything still ok.
./testscript.sh: Zeile 13: thisdoesnotexist: Kommando nicht gefunden.
Errorhandler called. Exiting.
在这种情况下,似乎不可能输出用户友好的消息(例如,其中包含发生错误的脚本中的步骤)。为此,我至少必须将函数名传递给错误陷阱。我试过了,但没有找到有效的解决办法


你有更好的建议吗?

如果你想做一些事情以防出错,并且你知道可能会出错,那么:

function_test () {
        echo "Everything still ok."
        thisdoesnotexist || {
          # handle thisdoesnotexist failure
          Echo "thisdoesnotexist failed" >&2
          exit 1
        }
        echo "It continues running..."
        if ! thisdoesnotexisteither; then
          # Handle fail for thisdoesnotexisteither
          Echo "thisdoesnotexisteither failed" >&2
          exit 1
        fi
}
现在,为了在Bash中测试错误处理,您可以使用以下智能错误处理功能:

#!/usr/bin/env bash

# Generate an error
# @Params
# $1: Numeric error return code
# ${2[@]}: Messages
# @Output
# &1: Generic success message
# &2: Generic or passed error messages
# @Return
# $?: Intended return code
erroring() {
  local rc=1
  if [ "$#" -gt 0 ]; then
    rc="$1"
    shift
    if printf '%d' "$rc" >/dev/null 2>&1; then
      # rc is an integer
      if [ "$rc" -gt 0 ]; then
        printf $"Intended failure with code: %d\\n" "$rc" >&2
        if [ "$#" -gt 0 ]; then
          # There are supplied messages to print"
          printf $"%d messages:\\n" "$#" >&2
          printf '%q\n' "$@" >&2
        fi
      else
        echo $"Intended success"
      fi
    else
      printf $"Invalid non-numeric return code parameter: %q\\n" "$rc" >&2
      rc=7
    fi
  else
    erroring "$rc"
  fi
  return "$rc"
}

函数测试| |{echo”在函数测试中发生错误。“退出1;}

由于函数返回状态的原因,OR从不发生。函数的最后一条echo语句导致返回状态为0,因为它已成功运行

如果在未成功执行的命令上添加非零返回,则会导致OR语句正常运行

function_test () {
        echo "Everything still ok."
        thisdoesnotexist || return 1;
        echo "It continues running..."
}

不太容易消耗,但在某些情况下更可取。导出标志和函数,并在子shell中运行它。处理bash错误值

#!/bin/bash
set -euo pipefail

function_test () {
    echo "Everything still ok."
    thisdoesnotexist
    echo "It continues running..."
}

export -f function_test
export SHELLOPTS
bash -c function_test || { echo "Error occured in function_test."; exit 1; }

最后一个
printf$”无效
-这是
printf$”无效
?递归调用
出错
有什么意义?如果[“$”-gt 0],不只是
;然后rc=$1;否则rc=1;fi
更简单吗?这是
出错
函数自行失败的原因,因为它被传递了一个非数字返回码。就像调用
出错“错误消息”
而不是调用
出错1“错误消息”