【问题标题】:Exit a Script On Error出错时退出脚本
【发布时间】:2011-05-21 20:44:20
【问题描述】:

我正在构建一个具有 if 函数的 Shell 脚本,如下所示:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

我希望在显示错误消息后完成脚本的执行。我该怎么做?

【问题讨论】:

    标签: bash exit shell


    【解决方案1】:

    如果您希望能够处理错误而不是盲目退出,而不是使用set -e,请在ERR 伪信号上使用trap

    #!/bin/bash
    f () {
        errorCode=$? # save the exit code as the first thing done in the trap function
        echo "error $errorCode"
        echo "the command executing at the time of the error was"
        echo "$BASH_COMMAND"
        echo "on line ${BASH_LINENO[0]}"
        # do some error handling, cleanup, logging, notification
        # $BASH_COMMAND contains the command that was being executed at the time of the trap
        # ${BASH_LINENO[0]} contains the line number in the script of that command
        # exit the script or return to try again, etc.
        exit $errorCode  # or use some other value or do return instead
    }
    trap f ERR
    # do some stuff
    false # returns 1 so it triggers the trap
    # maybe do some other stuff
    

    可以设置其他陷阱来处理其他信号,包括通常的 Unix 信号以及其他 Bash 伪信号 RETURNDEBUG

    【讨论】:

      【解决方案2】:

      你在找exit吗?

      这是最好的 bash 指南。 http://tldp.org/LDP/abs/html/

      在上下文中:

      if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
      then
          echo $jar_file signed sucessfully
      else
          echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
          exit 1 # terminate and indicate error
      fi
      
      ...
      

      【讨论】:

      • 如果你喜欢 ABS,你会喜欢 BashGuideBashFAQBashPitfalls
      • 那些 Bash 链接太棒了!将 BashFAQ 定位为 BashRecipes 会更好。
      【解决方案3】:

      方法如下:

      #!/bin/sh
      
      abort()
      {
          echo >&2 '
      ***************
      *** ABORTED ***
      ***************
      '
          echo "An error occurred. Exiting..." >&2
          exit 1
      }
      
      trap 'abort' 0
      
      set -e
      
      # Add your script below....
      # If an error occurs, the abort() function will be called.
      #----------------------------------------------------------
      # ===> Your script goes here
      # Done!
      trap : 0
      
      echo >&2 '
      ************
      *** DONE *** 
      ************
      '
      

      【讨论】:

      • 为什么将 DONE 消息发送到 stderr?
      • 这是一种常见的做法,因此您可以将脚本输出通过管道传输到标准输出,这样另一个进程就可以获取它,而不会在中间出现信息消息。
      • 将 stderr 上的任何内容视为问题的指示可能同样常见。
      • 过去 'set -e' 一直对我有用,但今晚我在 Alpine Linux Docker 映像中遇到了一个没有效果的情况。这个解决方案对我有用并让我受益回到手头的任务。非常感谢。
      • @supercobra 常见做法?在哪里?
      【解决方案4】:

      如果您将 set -e 放入脚本中,脚本将在其中的任何命令失败后立即终止(即,只要任何命令返回非零状态)。这不会让您编写自己的消息,但通常失败的命令自己的消息就足够了。

      这种方法的优点是它是自动的:您不会冒忘记处理错误情况的风险。

      状态由条件测试的命令(例如if&&||)不会终止脚本(否则条件将毫无意义)。对于失败无关紧要的偶尔命令的习语是command-that-may-fail || true。您也可以使用set +e 关闭部分脚本的set -e

      【讨论】:

      • 根据mywiki.wooledge.org/BashFAQ/105 - 此功能在确定哪些命令的错误代码会导致自动退出时一直晦涩难懂且令人费解。此外,“规则从一个 Bash 版本更改为另一个版本,因为 Bash 试图跟踪这个‘功能’的极其狡猾的 POSIX 定义”。我同意@Dennis Williamson 和接受的stackoverflow.com/questions/19622198/… 答案 - 使用陷阱'error_handler' ERR。就算是陷阱!
      • 经常使用-x 标志和-e 标志就足以跟踪您的程序退出的位置。这意味着脚本的用户也是开发者。
      • 很好,但我认为 OP 需要从自定义异常中退出脚本。
      【解决方案5】:

      exit 1 就是您所需要的。 1 是返回码,因此您可以根据需要更改它,例如,1 表示成功运行,-1 表示失败或类似情况。

      【讨论】:

      • 在 unix 中,成功总是 0。这在使用 test&&|| 时可能会有所帮助。
      • 扩展 mouviciel 的评论:在 shell 脚本中,0 始终表示成功,1 到 255 表示失败。 -1 超出范围(通常会产生与 255 相同的效果,因此像 1 一样失败)。
      • @mouviciel,@Gilles:感谢您提供的额外信息。自从我处理 bash 以来已经有一段时间了。
      • 这是一个不好的返回码使用示例,否则它会是一个很好的答案。
      • 除了错误地推荐 1 表示成功,-1 是不可能的(退出代码是无符号的)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      • 2011-02-24
      相关资源
      最近更新 更多