【问题标题】:How to check if $? is not equal to zero in unix shell scripting?如何检查是否为$?在 unix shell 脚本中不等于零?
【发布时间】:2013-03-18 06:58:49
【问题描述】:

我有一个脚本,它使用测试命令来检查$?(最后执行命令的返回码)是否不等于零。代码如下:-

$?是最后执行的命令的退出状态。

if (test $? -ne 0)
then
//statements//
fi

但是,这种验证方式不适用于字符串,因为 get syntax error 。请提出一个合适的替代方案。

【问题讨论】:

  • 在你的例子中,$?实际上是数字,但由于您确实使用了隐含的“测试”命令的方括号,因此您会遇到语法错误,而不是因为退出代码是字符串。
  • 谢谢......那么你有什么建议我应该尝试??
  • 请看下面我的回答,注意使用方括号,而不是括号...

标签: shell unix


【解决方案1】:

您无需测试$? 是否不是0。 Shell 提供了&&||,因此您可以轻松地根据该测试的隐式结果进行分支:

some_command && {
    # executes this block of code,
    # if some_command would result in:  $? -eq 0
} || {
    # executes this block of code,
    # if some_command would result in:  $? -ne 0
}

您可以删除任一分支,具体取决于您的需要。所以如果你只是想测试失败(即$? -ne 0):

some_command_returning_nonzero || {
    # executes this block of code when:     $? -ne 0
    # and nothing if the command succeeds:  $? -eq 0
}

但是,您在问题中提供的代码可以正常工作。我很困惑你有语法错误并得出结论 $? 是一个字符串。问题很可能没有提供导致语法错误的错误代码。这一点尤其明显,因为您声称没有其他人的解决方案也有效。发生这种情况时,您必须重新评估您的假设。

注意:如果大括号内的代码返回错误,上面的代码可能会产生令人困惑的结果。在这种情况下,只需使用if 命令,如下所示:

if some_command; then
    # executes this block of code,
    # if some_command would result in:  $? -eq 0
else
    # executes this block of code,
    # if some_command would result in:  $? -ne 0
fi

【讨论】:

  • "$? -eq 0" 表示 some_command 执行没有错误 ??和“$?-ne 0”有错误??
  • @happy,是的,这基本上是正确的:$? -eq 0 表示最后一个命令退出,状态码为0(成功)。 $? -ne 0 表示最后一个命令以非零状态码退出(通常是由于错误)。
  • 我已经在类似的 UC 中从管道切换到 if 块,因为它希望在错误情况下退出脚本。 (stackoverflow.com/a/20799125/1456164)
  • 谢谢你!太优雅了!
【解决方案2】:

先放到一个变量中,然后尝试测试,如下图

ret=$?
if [ $ret -ne 0 ]; then
        echo "In If"
else
        echo "In Else"
fi

这应该会有所帮助。


编辑:如果上面没有按预期工作,那么您可能没有在正确的位置使用$?它必须是您需要捕获返回状态的命令之后的下一行。即使在目标之间有任何其他单个命令并且您捕获它的返回状态,您也将检索到此中间命令的返回状态,而不是您所期望的。

【讨论】:

  • 我试过了......在我的情况下无法正常工作!任何其他建议请
  • @user1466466 - 你能扩展一下吗?你确定$? 正在返回你所期望的吗?用这个例子试试echo $ret 以确保。
  • 这对我有用。我通常很乐观,所以我改用[ $ret -eq 0 ],但这只是个人喜好问题。
  • @user1466466 我声称它应该可以工作。你能提供证据证明它没有吗?换句话说,永远不要只说“它不起作用”。告诉我们该命令做了什么,以及您希望它做什么。
  • @user1466466 请注意所有空格都很重要。例如,[ 和 $ret 之间有一个空格,以此类推。
【解决方案3】:

在你的脚本执行后试试这个:

if [ $? -ne 0 ];
then
//statements//
fi

【讨论】:

    【解决方案4】:

    这是针对类似问题提出的解决方案

    exit_status () {
    if [ $? = 0 ]
    then
        true
    else
        false
    fi
    }
    

    用法:

    do-command exit_status && echo "worked" || echo "didnt work"
    

    【讨论】:

    • 一个更简单的替代方法是这样定义它:exit_status() { test $? -eq 0; }。在您的示例中,您可以完全消除无关的 exit_status 函数并执行以下操作:do-command && echo "worked" || echo "didn't work"
    • 或者你可以这样做:stackoverflow.com/a/41308634/303114
    【解决方案5】:
    <run your last command on this line>
    a=${?}
    if [ ${a} -ne 0 ]; then echo "do something"; fi
    

    使用您想使用的任何命令代替echo "do something" 命令

    【讨论】:

      【解决方案6】:
      if [ $var1 != $var2 ] 
      then 
      echo "$var1"
      else 
      echo "$var2"
      fi
      

      【讨论】:

        【解决方案7】:

        我不知道你是如何在$? 中得到一个字符串的,但你可以这样做:

        if [[ "x$?" == "x0" ]]; then
           echo good
        fi
        

        【讨论】:

        • 我试过了......它无法检查条件!任何其他建议请
        • [[ ... ]] 在用户的 shell 中可能不可用。
        【解决方案8】:

        我整理了一些代码,这些代码可能有助于了解返回值与返回字符串的工作方式。可能有更好的方法,但这是我通过测试发现的。

        #!/bin/sh
        #
        # ro
        #
        
        pass(){
          echo passed
          return 0;   # no errors
        }
        fail(){
          echo failed
          return 1;   # has an error
        }
        t(){
          echo true, has error
        }
        f(){
          echo false, no error
        }
        
        dv=$(printf "%60s"); dv=${dv// /-}
        
        echo return code good for one use, not available for echo
        echo $dv
        pass
        [ $? -gt 0 ] && t || f
        echo "function pass: \$? $?" ' return value is gone'
        echo
        fail
        [ $? -gt 0 ] && t || f
        echo "function fail: \$? $?" ' return value is gone'
        echo
        
        echo save return code to var k for continued usage
        echo $dv
        pass
        k=$?
        [ $k -gt 0 ] && t || f
        echo "function pass: \$k $k"
        echo
        fail
        k=$?
        [ $k -gt 0 ] && t || f
        echo "function fail: \$k $k"
        echo
        
        # direct evaluation of the return value
        # note that (...) and $(...) executes in a subshell
        # with return value to calling shell
        # ((...)) is for math/string evaluation
        
        echo direct evaluations of the return value:
        echo '  by if (pass) and if (fail)'
        echo $dv
        if (pass); then
          echo pass has no errors
        else
          echo pass has errors
        fi
        if (fail); then
          echo fail has no errors
        else
          echo fail has errors
        fi
        
        # this code results in error because of returned string (stdout)
        # but comment out the echo statements in pass/fail functions and this code succeeds
        echo
        echo '  by if $(pass) and if $(fail) ..this succeeds if no echo to stdout from function'
        echo $dv
        if $(pass); then
          echo pass has no errors
        else
          echo pass has errors
        fi
        if $(fail); then
          echo fail has no errors
        else
          echo fail has errors
        fi
        
        echo
        echo '  by if ((pass)) and if ((fail)) ..this always fails'
        echo $dv
        if ((pass)); then
          echo pass has no errors
        else
          echo pass has errors
        fi
        if ((fail)); then
          echo fail has no errors
        else
          echo fail has errors
        fi
        
        echo 
        s=$(pass)
        r=$?
        echo pass, "s: $s  ,  r: $r"
        s=$(fail)
        r=$?
        echo fail, "s: $s  ,  r: $r"
        

        【讨论】:

          【解决方案9】:
          function assert_exit_code {
              rc=$?; if [[ $rc != 0 ]]; then echo "$1" 1>&2; fi
          }
          

          ...

          execute.sh
          
          assert_exit_code "execute.sh has failed"
          

          【讨论】:

            【解决方案10】:

            将 set -o pipefail 放在任何脚本的开头,以返回任何失败

            如果你这样做了,测试失败了,但发球台没有。默认情况下 $?只需要最后一个命令成功,在这种情况下是“tee”命令

            test | tee /tmp/dump
            [ $? -ne 0 ] && echo "failed"
            

            【讨论】:

              猜你喜欢
              • 2018-03-16
              • 1970-01-01
              • 2014-12-11
              • 1970-01-01
              • 1970-01-01
              • 2011-11-23
              • 1970-01-01
              • 1970-01-01
              • 2017-02-20
              相关资源
              最近更新 更多