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


当前回答

在每个命令之后,退出代码可以在$?变量,所以你会得到这样的东西:

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中。

其他回答

[ $? -eq 0 ] || exit $?; # Exit for nonzero return code

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

How do I get the exit code of cmd1 in cmd1|cmd2 First, note that cmd1 exit code could be non-zero and still don't mean an error. This happens for instance in cmd | head -1 You might observe a 141 (or 269 with ksh93) exit status of cmd1, but it's because cmd was interrupted by a SIGPIPE signal when head -1 terminated after having read one line. To know the exit status of the elements of a pipeline cmd1 | cmd2 | cmd3 a. with Z shell (zsh): The exit codes are provided in the pipestatus special array. cmd1 exit code is in $pipestatus[1], cmd3 exit code in $pipestatus[3], so that $? is always the same as $pipestatus[-1]. b. with Bash: The exit codes are provided in the PIPESTATUS special array. cmd1 exit code is in ${PIPESTATUS[0]}, cmd3 exit code in ${PIPESTATUS[2]}, so that $? is always the same as ${PIPESTATUS: -1}. ... For more details see Z shell.

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;
}
#
#------------------------------------------------------------------------------
# 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

}

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

command1 || exit;
command2 || exit;

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