如何使用if语句检查退出状态


254

我想知道在if语句中检查退出状态以回显特定输出的最佳方法是什么。

我在想

if [ $? -eq 1 ]
then
   echo "blah blah blah"
fi

我还遇到的问题是,退出语句位于if语句之前,仅仅是因为它必须具有该退出代码。另外,我知道我做错了,因为退出显然会退出程序。


3
Plaese发布您的完整脚本(或至少在更广泛的范围内)。否则,这似乎很好。
RedX 2014年

5
如果您需要在两个不同的地方一些特定的程序调用使用退出代码,那么你需要保留它-沿着线的东西some_program; rc=$?; if [ ${rc} -eq 1 ] .... fi ; exit ${rc}
twalberg

Answers:


261

运行的每个命令都具有退出状态。

该检查将查看该行运行之前最近完成的命令的退出状态。

如果你想你的脚本退出时测试返回true(以前的命令失败),那么你把exit 1(或其他)里面if块之后echo

话虽这么说,如果您正在运行命令并希望使用以下命令测试其输出通常会更加简单明了。

if some_command; then
    echo command returned true
else
    echo command returned some error
fi

或者将其!用于否定

if ! some_command; then
    echo command returned some error
else
    echo command returned true
fi

请注意,尽管这些都不关心错误代码是什么。如果知道只关心特定的错误代码,则需要$?手动检查。


11
@ deadcell4当需要在程序失败时终止shell脚本时,以下成语非常有用a_command || return 1
gboffi 2014年

10
@gboffi return仅在函数和源脚本中起作用。您需要exit其他情况(这在函数和源脚本中做得太多)。但是,是的,如果您不需要任何特定的清理或额外的输出,那肯定是一个合理的模式。
Etan Reisner,2014年

1
我不得不说,dash许多现代linux发行版中的默认非交互式shell不在乎已执行的shell脚本returnexit内部shell脚本之间的区别。dash退出脚本,即使我return在其中使用也是如此。
gboffi

最后两次检查背后的逻辑是什么?if <command>如果退出代码为0 ,则条件通过似乎是违反直觉的。在任何其他语言中,情况都是相反的
sjw

3
重要说明:这不适用于管道。 if ! some_command | some_other_command将忽略some_command的状态。最常见的两个命令解决方法是set -o pipefail(可能会更改程序其他部分的功能)或将if语句移动if [[ ${PIPESTATUS[0]} -ne 0 ]]为单独的后续命令(难看,但可以正常运行)。如果您正在使用,set -e那么|| true在使用第二种解决方案时,您还需要添加到管道的末尾,因为从提供的控制流中删除管道if会导致其立即退出。
Alex Jansen

186

请注意,退出代码!= 0用于报告错误。因此,最好这样做:

retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error"
fi
exit $retVal

代替

# will fail for error codes > 1
retVal=$?
if [ $retVal -eq 1 ]; then
    echo "Error"
fi
exit $retVal

您必须在retVal上进行测试,因为$?在分配retVal之后,它不是命令的返回值。
anr78 '18

并非如此:mywiki.wooledge.org/BashFAQ/002-但是,我同意编辑可以提高可读性。
Oo.oO

1
刚刚发现这个职位,说明它stackoverflow.com/questions/20157938/...
anr78

dnf check-update返回0(无更新),100(可用更新)或1(错误)。
jww

1
@jww-好吧,这不是违反约定的好主意(gnu.org/software/bash/manual/html_node/Exit-Status.html)。但是,没有什么可以防止这种情况的发生。如果dnf开发人员选择了这种方式,那是他们的选择。但仍然,他们的选择并没有破坏规范:)
Oo.oO

44

$?与其他参数一样。您可以保存其值以在最终调用之前使用exit

exit_status=$?
if [ $exit_status -eq 1 ]; then
    echo "blah blah blah"
fi
exit $exit_status

29

替代显式 if陈述

最少:

test $? -eq 0 || echo "something bad happened"

完成:

EXITCODE=$?
test $EXITCODE -eq 0 && echo "something good happened" || echo "something bad happened"; 
exit $EXITCODE

13

只是添加到有用和详细的答案

如果必须显式检查退出代码,则最好通过以下方式使用算术运算符(( ... ))

run_some_command
(($? != 0)) && { printf '%s\n' "Command exited with non-zero"; exit 1; }

或者,使用以下case语句:

run_some_command; ec=$?  # grab the exit code into a variable so that it can
                         # be reused later, without the fear of being overwritten
case $ec in
    0) ;;
    1) printf '%s\n' "Command exited with non-zero"; exit 1;;
    *) do_something_else;;
esac

有关Bash中错误处理的相关答案:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.