如果命令失败,如何退出?

时间:2010-09-29 14:32:38

标签: linux bash exit exitstatus

我是shell脚本中的菜鸟。如果命令失败,我想打印一条消息并退出我的脚本。我试过了:

my_command && (echo 'my_command failed; exit)

但它不起作用。它不断执行脚本中此行之后的指令。我正在使用Ubuntu和bash。

10 个答案:

答案 0 :(得分:326)

尝试:

my_command || { echo 'my_command failed' ; exit 1; }

四处变化:

  • &&更改为||
  • 使用{ }代替( )
  • ;
  • 之后介绍exit
  • {之后和}
  • 之前的空格

由于您要打印消息并仅在命令失败时退出(以非零值退出),您需要||而不是&&

cmd1 && cmd2
cmd2成功时,

将运行cmd1(退出值0)。

cmd1 || cmd2
cmd2失败时,

将运行cmd1(退出值非零)。

使用( )使其中的命令在 子shell 中运行,并从那里调用exit会导致您退出子-shell而不是原始shell,因此在原始shell中继续执行。

要克服此用途{ }

bash需要最后两次更改。

答案 1 :(得分:116)

其他答案很好地涵盖了直接问题,但您可能也有兴趣使用set -e。这样,任何失败的命令(在if测试之类的特定上下文之外)都将导致脚本中止。对于某些脚本,它非常有用。

答案 2 :(得分:56)

如果您希望脚本中的所有命令都具有该行为,只需添加

即可
  set -e 
  set -o pipefail

在脚本的开头。这对选项告诉bash解释器在命令以非零退出代码返回时退出。

但是,这不允许您打印退出消息。

答案 3 :(得分:54)

另请注意,每个命令的退出状态都存储在shell变量$?中,您可以在运行命令后立即检查。非零状态表示失败:

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi

答案 4 :(得分:11)

我已经破解了以下习语:

echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Done."

在每个命令前面都有一个信息性回声,并按照每个命令使用相同的信息  if [ $? -ne 0 ];...行。 (当然,如果您愿意,可以编辑该错误消息。)

答案 5 :(得分:10)

如果my_command是规范设计的,成功时返回0,那么&&正好与您想要的相反。你想要||

另请注意,(在bash中对我来说似乎不对,但我不能尝试从哪里开始。告诉我。

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}

答案 6 :(得分:3)

如果要保留退出错误状态,还可以使用可读文件,每行一个命令:

my_command1 || exit $?
my_command2 || exit $?

然而,这不会打印任何其他错误消息。但在某些情况下,错误将由失败的命令打印出来。

答案 7 :(得分:3)

trap shell内置函数允许捕获信号和其他有用条件,包括失败的命令执行(即非零返回状态)。因此,如果您不想显式测试每个命令的返回状态,您可以说trap "your shell code" ERR,并且只要命令返回非零状态,就会执行shell代码。例如:

trap "echo script failed; exit 1" ERR

请注意,与其他捕获失败命令的情况一样,管道需要特殊处理;以上不会抓住false | true

答案 8 :(得分:2)

直接使用 exit 可能会很棘手,因为脚本可能来自其他地方(例如来自终端)。我更喜欢使用带有 set -e 的子shell(加上错误应该进入cerr,而不是cout):

set -e
ERRCODE=0
my_command || ERRCODE=$?
test $ERRCODE == 0 ||
    (>&2 echo "My command failed ($ERRCODE)"; exit $ERRCODE)

答案 9 :(得分:0)

以下功能仅在命令失败时回显错误:

silently () {
    label="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${label}: ${error}" >&2
        exit 1
    fi
}