Aborting a shell script if any command returns a non-zero value
Add this to the beginning of the script:
set -e
This will cause the shell to exit immediately if a simple command exits with a nonzero exit value. A simple command is any command not part of an if, while, or until test, or part of an && or || list.
See the bash(1) man page on the "set" internal command for more details.
I personally start almost all shell scripts with "set -e". It's really annoying to have a script stubbornly continue when something fails in the middle and breaks assumptions for the rest of the script.
Exiting a shell-script at the end with a non-zero code if any command fails
One possible way would be to catch the non-zero exit code via trap
with ERR
. Assuming your tests don't contain pipelines |
and just return the error code straight to the shell launched, you could do
#!/usr/bin/env bash
exitCodeArray=()
onFailure() {
exitCodeArray+=( "$?" )
}
trap onFailure ERR
# Add all your tests here
addNumbers () {
local IFS='+'
printf "%s" "$(( $* ))"
}
Add your tests anywhere after the above snippet. So we keep adding the exit code to the array whenever a test returns a non-zero return code. So for the final assertion we check if the sum of the array elements is 0
, because in an ideal case all cases should return that if it is successful. We reset the trap
set before
trap '' ERR
if (( $(addNumbers "${exitCodeArray[@]}") )); then
printf 'some of your tests failed\n' >&2
exit -1
fi
How to exit from shell script if any of the command in SSH returns non-zero value
Keep in mind that your set -e
idea applies just as well to the shell you open on the other end with ssh. So you can prepend your ssh commands with that to ensure an error terminates the ssh session:
$SSH $user@$remoteIpAddress "set -e; sudo rm -rf $remoteLocation/xxx/*; cd $remoteLocation/yyy; .... ... "
Then the ssh shell will exit with non-zero error code as soon as an error is encountered, and your script will exit as well if you have set -e
earlier in your script.
How can I make a shell script exit when any command in it fails?
Putting &&
between commands will tell bash to execute commands from start to end, and if any fail along the way, it will stop executing.
For example:
echo $(non_existent_variable) && cd ~
cd ~
is a valid command. However, since non_existent_variable
is not defined, the first command fails and an error is thrown immediately.
In your case, you can add && \
at the end of each of your lines.
Automatically exit when bash command produce return code non zero
There are lots of problems with using set -e
. Just join the commands with &&
, and test the result with an if
statement.
if cd /something_something && mv file_a /somedir/file_a; then
echo $?
exit
fi
echo "Both cd and mv worked"
Bash Script - If Pyscript Returns Non-zero, Write Errors to Output File AND Quite Bash Script
The exit status of a pipeline is the status of the last command, so $?
is the status of tee
, not pytest
.
In bash
you can use the $PIPESTATUS
array to get the status of each command in the pipeline.
python3 run_tests.py 2>&1 | tee tests.log
status=${PIPESTATUS[0]} # status of run_tests.py
if [ $status -ne 0 ]; then
echo 'ERROR: pytest failed, exiting ...'
exit $status
fi
Note that you need to save the status in another variable, because $?
and $PIPESTATUS
are updated after each command.
non-zero value of 2 numbers with a return exit code in shell
You want to return two exit codes at the same time? I guess that, when driving a car, you also want to sit on the front seat and on the back seat at the same time. You can do it, but you need a special car for this. Here are two ideas for making such a car:
If you know that in this context each exit code must be a 1-digit number, you could return something like
$((RC*10+RC2))
- I'm using bash/zsh syntax here, as you didn't say which shell you are using. If necessary, you have to adapt this to your shell.You could adapt the interface of your script, by printing something like "$RC1 $RC2" to stderr if at least one of them is non-zero, i.e.:
if [ $RC -ne 0 ] || [ $RC1 -ne 0 ]; then
echo "$RC $RC1" 1>&2
exit 1
else
exit 0
fi
In both cases, the calling process has to take apart the combined exit code to get back the original ones.
Exit Shell Script Based on Process Exit Code
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.
Related Topics
How to Tar a Directory Without Retaining the Directory Structure
Is There a Way For Non-Root Processes to Bind to "Privileged" Ports on Linux
Redirect All Output to File in Bash
Appending a Line to a File Only If It Does Not Already Exist
Use of Floating Point in the Linux Kernel
Controlling a Usb Power Supply (On/Off) With Linux
[ :Unexpected Operator in Shell Programming
Change the X-Frame-Options to Allow All Domains
How to Exclude a Directory When Using 'Find'
How to Merge Two "Ar" Static Libraries into One
Difference Between Clock_Realtime and Clock_Monotonic
Docker Can't Connect to Docker Daemon
How to Quickly Sum All Numbers in a File