基于进程退出码退出Shell脚本

我有一个shell脚本,执行一些命令。我如何使shell脚本退出,如果任何命令退出与非零退出码?

430032 次浏览

在Bash中,这很简单。只需用&&将它们连接在一起:

command1 && command2 && command3

你也可以使用嵌套的如果结构:

if command1
then
if command2
then
do_something
else
exit
fi
else
exit
fi

在每个命令之后,退出码可以在$?变量中找到,所以你会有类似的东西:

ls -al file.ext
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

你需要小心管道命令,因为$?只给你管道中最后一个元素的返回代码,所以,在代码中:

ls -al file.ext | sed 's/^/xx: /"

如果文件不存在,将不会返回错误代码(因为管道的sed部分实际工作,返回0)。

bash shell实际上提供了一个可以在这种情况下提供帮助的数组,即PIPESTATUS。这个数组为每个管道组件都有一个元素,你可以像${PIPESTATUS[0]}那样单独访问:

pax> false | true ; echo ${PIPESTATUS[0]}
1

请注意,这将为您提供false命令的结果,而不是整个管道。你也可以得到整个列表来处理你认为合适的:

pax> false | true | false; echo ${PIPESTATUS[*]}
1 0 1

如果你想从管道中获得最大的错误代码,你可以使用如下代码:

true | true | false | true | false
rcs=${PIPESTATUS[*]}; rc=0; for i in ${rcs}; do rc=$(($i > $rc ? $i : $rc)); done
echo $rc

这将依次遍历每个PIPESTATUS元素,如果它大于前一个rc值,则将其存储在rc中。

set -e”可能是最简单的方法。只要把它放在程序中的任何命令之前。

如果你想使用$?,你需要在每个命令后检查它,因为$?在每个命令退出后都会更新。这意味着如果您执行一个管道,您将只获得管道中最后一个进程的退出码。

另一种方法是这样做:

set -e
set -o pipefail

如果将它放在shell脚本的顶部,Bash似乎会为您处理它。正如之前的海报所指出的,“set -e"将导致Bash在任何简单命令上都出错退出。“set -o pipefail”;也会导致Bash在管道中的任何命令上出现错误而退出。

有关这个问题的更多讨论,请参见在这里在这里在这里是内置set的Bash手册部分。

如果在Bash中只调用exit而不带任何参数,它将返回上一个命令的退出代码。结合OR, Bash应该只在前面的命令失败时调用exit。但是我还没有测试过。

command1 || exit;
command2 || exit;

Bash还将最后一个命令的退出码存储在变量$?中。

Bash的:

# This will trap any errors or commands with non-zero exit status
# by calling function catch_errors()
trap catch_errors ERR;


#
# ... the rest of the script goes here
#


function catch_errors() {
# Do whatever on errors
#
#
echo "script aborted, because of errors";
exit 0;
}

http://cfaj.freeshell.org/shell/cus-faq-2.html#11

  1. 我如何在cmd1|cmd2中获得cmd1的退出代码

    首先,请注意cmd1退出码可以是非零,但仍然不意味着错误。这发生在

    cmd | head -1
    

    你可能会观察到cmd1的141(或带有ksh93的269)退出状态,但这是因为当head -1读取一行后终止时,cmd被SIGPIPE信号中断。

    了解管道元素的退出状态 cmd1 | cmd2 | cmd3 < / p >

    a. with Z shell (zsh):

    退出码在pipestatus特殊数组中提供。 cmd1退出码在$pipestatus[1]cmd3退出码在 $pipestatus[3],使$?始终与 $pipestatus[-1] . < / p >

    b.使用Bash:

    退出码在PIPESTATUS特殊数组中提供。 cmd1退出码在${PIPESTATUS[0]}cmd3退出码在 ${PIPESTATUS[2]},使$?始终与 ${PIPESTATUS: -1} . < / p >

    ...

    更多细节见Z shell

[ $? -eq 0 ] || exit $?; # Exit for nonzero return code
#
#------------------------------------------------------------------------------
# purpose: to run a command, log cmd output, exit on error
# usage:
# set -e; do_run_cmd_or_exit "$cmd" ; set +e
#------------------------------------------------------------------------------
do_run_cmd_or_exit(){
cmd="$@" ;


do_log "DEBUG running cmd or exit: \"$cmd\""
msg=$($cmd 2>&1)
export exit_code=$?


# If occurred during the execution, exit with error
error_msg="Failed to run the command:
\"$cmd\" with the output:
\"$msg\" !!!"


if [ $exit_code -ne 0 ] ; then
do_log "ERROR $msg"
do_log "FATAL $msg"
do_exit "$exit_code" "$error_msg"
else
# If no errors occurred, just log the message
do_log "DEBUG : cmdoutput : \"$msg\""
fi


}