Exit codes and statuses
Everytime a command is executed it returns an exit code
. All the following names refer the same thing: return status
,exit status
or exit code
.
Exit code value is an integer, ranging from 0 to 255.
By convention, successfully executed command return a exit code 0. A non-zero exit code is returned if some kind of error/failure is encountered.
These exit codes can be used for error checking in your scripts. Tests can be simple, like; was the exit code 0, or more complex, like; a specific error code.
If you want find out what the various exit codes a command can return, you have to manually test them or take a look at the manual of the command or it's source code. Try out a man
or info
commands combined with a desired command to read the documention (usually not mentioned).
As an example; grep
commands documention explains the following: > Normally the exit status is 0 if a line is selected, 1 if no lines
were selected, and 2 if an error occurred. However, if the -q or
--quiet or --silent is used and a line is selected, the exit
status is 0 even if an error occurred.
Just remember the basics: 0 for success, non-zero for some sort of error.
The special variable $?
contains the exit status of the last command executed.
And with a functions, $? gives the exit status of the last command executed in the function, unless a return
is not manually defined.
In the following example, ls command is called with a file path that doesnt exist.
#!/bin/bash
ls /path/not/available #invalid file path
echo ${?} #print exit code
#output:
#ls: /path/not/available: No such file or directory
#2
Exit command
Like you allready know, normal commands and shell scripts return an exit code. When the exit command is reached, shell script will stop running. You can control the exit code of your shell script by using a exit command. Simply use the exit
command followed by a integer 0 to 255.
If no "manual" exit is not specified, the latest commands exit code is used.
ls $HOME #command will succeed
exit 100 # return your own exit code
#echo $1 #test it in you shell
Exit codes can be used to make decisions or perform a different actions based on the exit code.
In the following example, script tries to create a new folder and command's return code is checked. If the command returns 0, 0 is returned from the script, if the command returns a non-zero value, script returns exit code 1 and exits.
#!/bin/bash
read -p "give a new folder: " FOLDER
mkdir ${FOLDER}
#If mkdir command fails, command returns exit code 1
#In that case the if stament becames true, and the block inside of it will be executed
#Exit 1 line stops the execution of the script and exit code 1 is returned
#Test this on you shell after the script execution: echo $?
if [ ${?} -ne 0 ]
then
echo "cannot create a folder: ${FOLDER}"
exit 1
fi
exit 0
If you dont't like to use a special variable, you can assign the return code of the command to a other variable and then use that variable in you script.
just remember to assign a value to a variable immediatly after the command!
#!/bin/bash
read -p "give a new folder: " FOLDER
mkdir ${FOLDER}
EXIT_CODE=$?
if [ ${EXIT_CODE} -ne 0 ]
then
echo "cannot create a folder: ${FOLDER}"
exit 1
fi
exit 0
Exit codes and a logical operators?
In addition to using if staments to analyse exit statuses, logical ANDs (&&
) and ORs (||
) can be used.
A command that is following a AND operator, will only execute if the previous command succeeds (returns 0).
#!/bin/bash
mkdir /testfolder && ls /testfolder #The second command will not be executed because folder cannot be created
#output:
#mkdir: cannot create directory ‘/testfolder’: Permission denied
A command that following a OR operator, will only execute if the previous command fails (returns non-zero code).
#!/bin/bash
mkdir /home/user/testfolder || mkdir /tmp/testfolder #The first command succeeds, no need to execute the second one
#output: /home/user/testfolder was created
#or the other way around
mkdir /testfolder || mkdir /tmp/testfolder #The first command fails (returns non-zero), try the second one
#output: /tmp/testfolder was created
If you want to chain commands together in a single line without exit code checking, use a semicolon (;
) between commands. That way the commands will be always get executed, no matter if the previous command failed or succeeded.
#!/bin/bash
#earlier 'and' example
mkdir /testfolder ; ls /testfolder
#Is the same as
mkdir /testfolder
ls /testfolder
#Output for both styles will be:
#mkdir: cannot create directory ‘/testfolder’: Permission denied
#ls: cannot access '/testfolder': No such file or directory