【问题标题】:Exit a bash script from a function whose output is captured从输出被捕获的函数中退出 bash 脚本
【发布时间】:2013-01-17 11:51:25
【问题描述】:

我想在出错时完全终止/退出 bash shell 脚本,但使用函数error 让我在终止前显示调试输出。现在我遇到的问题是,如果函数的输出是通过反引号或$() 捕获的,则错误函数中的exit 1 语句将终止shell 脚本。

这是我的示例脚本:

    #!/bin/bash

    function error ()
    {
            echo "An error has occured: $1"
            exit 1
    }
    function do_sth ()
    {
            if [ $1 -eq 0 ]; then
                    error "First param must be greater than 0!"
            else
                    echo "OK!"
            fi
    }

    RESULT=`do_sth 0`

    echo "This line should never be printed"

如何立即终止 error() 函数中的脚本?

【问题讨论】:

    标签: linux bash shell sh


    【解决方案1】:

    command substitution 的问题是,一个子shell 开始执行do_sthexit 1 然后终止这个 subshel​​l 而不是主 bash。

    您可以通过附加|| exit $? 来解决此问题,它使用命令替换的退出代码退出

    RESULT=`do_sth 0` || exit $?
    

    如果要显示错误信息,请将其重定向到 stderr

    echo "An error has occured: $1" >&2
    

    【讨论】:

    • 该解决方案的问题是,错误函数生成的实际错误消息不会被打印出来
    【解决方案2】:
    RESULT=`do_sth 0` || exit $?
    

    那么 echo "发生错误:$1" >&2

    【讨论】:

      【解决方案3】:

      没有办法避免子shell 不能直接终止父进程的事实:父进程必须评估从子shell 返回的值。一种常见的技术是陷阱退出并在陷阱函数中打印错误消息。由于您在子 shell 中生成错误消息,因此您不能像其他方式那样简单地将消息分配给变量,但您可以使用文件系统。请注意,这个想法真的很傻,简单地将错误消息写入stderr要干净得多。这就是它的用途,这就是它被孩子继承的原因。比如:

      #!/bin/sh
      
      trap final 0 2 15
      
      # Create a temporary file to store error messages.  This is a terrible
      # idea: it would be much better to simply write error messages to stderr,
      # but this code is attempting to demonstrate the technique of having the
      # parent print the message.  Perhaps it would do better to serve as an example
      # of why reporting your children's mistakes is a bad idea.  The children
      # should be responsible for reporting their own errors.  Doing so is easy,
      # since they inherit file descriptor 2 from their parent.
      errmsg=$( mktemp xxxxx )
      final() {
          test "$?" = 0 || cat $errmsg
          rm -f $errmsg
      } >&2
      
      # Must emphasize one more time that this is a silly idea.  The error 
      # function ought to be writing to stderr: eg echo "error: $*" >&2
      error() { echo "error: $*" > $errmsg; exit 1; }
      do_sth() { 
          if test "$1" -eq 0; then
              error "First param must be greater than 0!"
          else
              echo "OK!"
          fi
      }
      
      
      result=$( do_sth 0 ) || exit 1
      echo not printed
      

      【讨论】:

        【解决方案4】:

        似乎(聪明的)答案是@FatalError,here on so

        的另一个问题的最佳答案

        【讨论】:

          【解决方案5】:

          这应该可以...

          #!/bin/bash
          
          trap "exit 1" 50                                       #exit process after receiving signal 50.
          
          function myerror ()
          {
              echo "An error has occured: $1" >&2
          }
          function do_sth ()
          {
              if [ $1 -eq 0 ]; then
                  myerror "First param must be greater than 0!"
                  kill -50 $(ps --pid $$ -opid=)                 #uncommon signal 50 is used.
              else
                  echo "OK!"
              fi
          }
          
          RESULT=`do_sth 1`
          echo $RESULT
          
          RESULT=`do_sth 0`
          echo $RESULT
          
          echo "This line should never be printed"
          

          【讨论】:

          • 你可以有多个这样的信号,比如这里使用的 50,因此不同的退出状态......
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-15
          • 1970-01-01
          • 2019-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多