Exit Shell Script Based on Process Exit Code

2019-01-03 19:24发布

I have a shell script that executes a number of commands. How do I make the shell script exit if any of the commands exit with a non-zero exit code?

标签: bash shell
9条回答
在下西门庆
2楼-- · 2019-01-03 19:39

In bash this is easy, just tie them together with &&:

command1 && command2 && command3

You can also use the nested if construct:

if command1
   then
       if command2
           then
               do_something
           else
               exit
       fi
   else
       exit
fi
查看更多
劫难
3楼-- · 2019-01-03 19:42

After each command, the exit code can be found in the $? variable so you would have something like:

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

You need to be careful of piped commands since the $? only gives you the return code of the last element in the pipe so, in the code:

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

will not return an error code if the file doesn't exist (since the sed part of the pipeline actually works, returning 0).

The bash shell actually provides an array which can assist in that case, that being PIPESTATUS. This array has one element for each of the pipeline components, that you can access individually like ${PIPESTATUS[0]}:

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

Note that this is getting you the result of the false command, not the entire pipeline. You can also get the entire list to process as you see fit:

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

If you wanted to get the largest error code from a pipeline, you could use something like:

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

This goes through each of the PIPESTATUS elements in turn, storing it in rc if it was greater than the previous rc value.

查看更多
Juvenile、少年°
4楼-- · 2019-01-03 19:43

for 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;
}
查看更多
疯言疯语
5楼-- · 2019-01-03 19:44
[ $? -eq 0 ] || exit $?; # exit for none-zero return code
查看更多
对你真心纯属浪费
6楼-- · 2019-01-03 19:44

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

  1. 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 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 the following link.

查看更多
乱世女痞
7楼-- · 2019-01-03 19:45

"set -e" is probably the easiest way to do this. Just put that before any commands in your program.

查看更多
登录 后发表回答