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


当前回答

在Bash中,这很简单。用&&把它们连在一起:

command1 && command2 && command3

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

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

其他回答

在Bash中,这很简单。用&&把它们连在一起:

command1 && command2 && command3

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

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

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;
}
[ $? -eq 0 ] || exit $?; # Exit for nonzero return code

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

另一种方法是这样做:

set -e
set -o pipefail

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

有关这个问题的更多讨论,请参见这里或这里。下面是Bash手册中关于内置设置的部分。