Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exit Shell Script Based on Process Exit Code [duplicate]

Tags:

bash

shell

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?

like image 276
Mark Roddy Avatar asked Sep 18 '08 06:09

Mark Roddy


People also ask

How do you exit a script in shell script?

To end a shell script and set its exit status, use the exit command. Give exit the exit status that your script should have. If it has no explicit status, it will exit with the status of the last command run.

What is exit 2 in shell script?

Exit code 2 signifies invalid usage of some shell built-in command. Examples of built-in commands include alias, echo, and printf.

What is exit 10 in shell script?

Exit Codes. Exit codes are a number between 0 and 255, which is returned by any Unix command when it returns control to its parent process. Other numbers can be used, but these are treated modulo 256, so exit -10 is equivalent to exit 246 , and exit 257 is equivalent to exit 1 .


3 Answers

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.

like image 175
paxdiablo Avatar answered Oct 22 '22 06:10

paxdiablo


If you want to work with $?, you'll need to check it after each command, since $? is updated after each command exits. This means that if you execute a pipeline, you'll only get the exit code of the last process in the pipeline.

Another approach is to do this:

set -e
set -o pipefail

If you put this at the top of the shell script, it looks like Bash will take care of this for you. As a previous poster noted, "set -e" will cause Bash to exit with an error on any simple command. "set -o pipefail" will cause Bash to exit with an error on any command in a pipeline as well.

See here or here for a little more discussion on this problem. Here is the Bash manual section on the set builtin.

like image 23
Jeff Hill Avatar answered Oct 22 '22 04:10

Jeff Hill


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

like image 54
Allen Avatar answered Oct 22 '22 04:10

Allen