我是shell脚本的菜鸟 . 如果命令失败,我想打印一条消息并退出我的脚本 . 我试过了:
my_command && (echo 'my_command failed; exit)
但它不起作用 . 它继续执行脚本中此行之后的指令 . 我正在使用Ubuntu和bash .
trap shell内置允许捕获信号和其他有用条件,包括失败的命令执行(即,非零返回状态) . 因此,如果您不想显式测试每个命令的返回状态,您可以说 trap "your shell code" ERR ,并且只要命令返回非零状态,就会执行shell代码 . 例如:
trap
trap "your shell code" ERR
trap "echo script failed; exit 1" ERR
请注意,与捕获失败命令的其他情况一样,管道需要特殊处理;以上不会 grab false | true .
false | true
如果您希望脚本中的所有命令都具有该行为,则只需添加
set -e set -o pipefail
在脚本的开头 . 这对选项告诉bash解释器在命令以非零退出代码返回时退出 .
但是,这不允许您打印退出消息 .
其他答案很好地涵盖了直接问题,但您可能也有兴趣使用 set -e . 这样,任何失败的命令(在特定上下文之外,如 if tests)都会导致脚本中止 . 对于某些脚本,它非常有用 .
set -e
if
我已经破解了以下习语:
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 ];... 行 . (当然,如果您愿意,可以编辑该错误消息 . )
if [ $? -ne 0 ];...
尝试:
my_command || { echo 'my_command failed' ; exit 1; }
四个变化:
将 && 更改为 ||
&&
||
使用 { } 代替 ( )
{ }
( )
exit 后引入 ;{ 之后 } 之前
exit
;
{
}
个空格
由于您要打印消息并仅在命令失败时退出(以非零值退出),您需要 || 而不是 && .
cmd1 && cmd2
当 cmd1 成功(退出值 0 )时,将运行 cmd2 . 在哪里
cmd1
0
cmd2
cmd1 || cmd2
cmd1 失败时退出 cmd2 (退出值非零) .
使用 ( ) 使其中的命令在 sub-shell 中运行并从那里调用 exit 导致您退出子shell而不是原始shell,因此在原始shell中继续执行 .
要克服这个用途 { }
bash需要最后两个更改 .
如果 my_command 是规范设计的,即成功时返回0,则 && 正好与您想要的相反 . 你想 || .
my_command
另请注意_b4771_在bash中对我来说似乎不对,但我不能尝试从哪里开始 . 告诉我 .
另请注意,每个命令的退出状态都存储在shell变量$?中,您可以在运行命令后立即检查 . 非零状态表示失败:
my_command if [ $? -eq 0 ] then echo "it worked" else echo "it failed" fi
如果要保留退出错误状态,还可以使用可读文件,每行一个命令:
my_command1 || exit $? my_command2 || exit $?
但是,这不会打印任何其他错误消息 . 但在某些情况下,错误将由失败的命令打印 .
对于 error proofing 您的命令:
execute [INVOKING-FUNCTION] [COMMAND]
execute () { error=$($2 2>&1 >/dev/null) if [ $? -ne 0 ]; then echo "$1: $error" exit 1 fi }
Inspired 精益 生产环境 :
Make errors impossible by design
Make steps the smallest
Finish items one by one
Make it obvious to anyone
9 回答
trap
shell内置允许捕获信号和其他有用条件,包括失败的命令执行(即,非零返回状态) . 因此,如果您不想显式测试每个命令的返回状态,您可以说trap "your shell code" ERR
,并且只要命令返回非零状态,就会执行shell代码 . 例如:trap "echo script failed; exit 1" ERR
请注意,与捕获失败命令的其他情况一样,管道需要特殊处理;以上不会 grab
false | true
.如果您希望脚本中的所有命令都具有该行为,则只需添加
在脚本的开头 . 这对选项告诉bash解释器在命令以非零退出代码返回时退出 .
但是,这不允许您打印退出消息 .
其他答案很好地涵盖了直接问题,但您可能也有兴趣使用
set -e
. 这样,任何失败的命令(在特定上下文之外,如if
tests)都会导致脚本中止 . 对于某些脚本,它非常有用 .我已经破解了以下习语:
在每个命令前面都有一个信息性回声,并按照每个命令使用相同的命令
if [ $? -ne 0 ];...
行 . (当然,如果您愿意,可以编辑该错误消息 . )尝试:
四个变化:
将
&&
更改为||
使用
{ }
代替( )
exit
后引入;
{
之后}
之前个空格
由于您要打印消息并仅在命令失败时退出(以非零值退出),您需要
||
而不是&&
.当
cmd1
成功(退出值0
)时,将运行cmd2
. 在哪里cmd1
失败时退出cmd2
(退出值非零) .使用
( )
使其中的命令在 sub-shell 中运行并从那里调用exit
导致您退出子shell而不是原始shell,因此在原始shell中继续执行 .要克服这个用途
{ }
bash需要最后两个更改 .
如果
my_command
是规范设计的,即成功时返回0,则&&
正好与您想要的相反 . 你想||
.另请注意_b4771_在bash中对我来说似乎不对,但我不能尝试从哪里开始 . 告诉我 .
另请注意,每个命令的退出状态都存储在shell变量$?中,您可以在运行命令后立即检查 . 非零状态表示失败:
如果要保留退出错误状态,还可以使用可读文件,每行一个命令:
但是,这不会打印任何其他错误消息 . 但在某些情况下,错误将由失败的命令打印 .
对于 error proofing 您的命令:
Inspired 精益 生产环境 :
Make errors impossible by design
Make steps the smallest
Finish items one by one
Make it obvious to anyone