我在编写shell脚本方面是个新手。如果命令失败,我想打印一条消息并退出脚本。我试过了:

my_command && (echo 'my_command failed; exit)

但这并不奏效。它继续执行脚本中这一行之后的指令。我使用Ubuntu和bash。


当前回答

内置的trap shell允许捕获信号和其他有用的条件,包括失败的命令执行(即非零返回状态)。因此,如果你不想显式地测试每个命令的返回状态,你可以输入“你的shell代码”ERR,当命令返回非零状态时,shell代码将被执行。例如:

返回脚本失败;exit 1" ERR

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

其他回答

内置的trap shell允许捕获信号和其他有用的条件,包括失败的命令执行(即非零返回状态)。因此,如果你不想显式地测试每个命令的返回状态,你可以输入“你的shell代码”ERR,当命令返回非零状态时,shell代码将被执行。例如:

返回脚本失败;exit 1" ERR

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

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

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

set -e 
set -o pipefail

在脚本的开头。这对选项告诉bash解释器,当命令返回非零退出码时,就退出。(更多关于为什么需要pipefail的详细信息,请参见http://petereisentraut.blogspot.com/2010/11/pipefail.html)

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

还要注意,每个命令的退出状态都存储在shell变量$?,可在执行命令后立即查看。非零状态表示失败:

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

Try:

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

四个变化:

将&&改为|| 用{}代替() 介绍;退出后, {和}之前的空格

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

cmd1 && cmd2

当cmd1成功时将运行cmd2(退出值为0)

cmd1 || cmd2

当cmd1失败时将运行cmd2(退出值非零)。

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

要克服这个问题,请使用{}

bash需要最后两个更改。