Shell Scripts for Beginners
Shebang
Exit Codes
In this article, we explore the concept of exit codes in shell scripts and how they indicate whether a command executed successfully or encountered an error on Linux systems.
When you run a command, it either executes successfully or fails. For instance, listing the contents of the current directory with the command below executes successfully and returns an exit status of zero:
$ ls
/home/root/tmp
Conversely, if you run a command that does not exist, an error is displayed and a non-zero exit code is returned:
$ lss
Failed: command not found
When a command runs successfully, it returns an exit status of 0; when it fails, it returns a non-zero value. These exit codes are not shown in the command output but are stored in the built-in variable "$?".
To view the exit code immediately after executing a command, use:
$ ls
/home/root/tmp
$ echo $?
0
$ lss
Failed: command not found
$ echo $?
127
Note
It is considered best practice to use exit codes in your scripts to communicate the overall status to the caller or user.
Consider a scenario where you are launching a rocket mission. For a successful launch, the script should return an exit status of 0, and for any failure, it should explicitly return a non-zero value (commonly 1).
Below is a sample script that starts a rocket launch mission. In this naive version, even if the launch fails, the script returns an exit code of 0 because it only prints a failure message without setting a non-zero index:
mkdir $mission_name
rocket-add $mission_name
rocket-start-power $mission_name
rocket-internal-power $mission_name
rocket-start-sequence $mission_name
rocket-start-engine $mission_name
rocket-lift-off $mission_name
rocket_status=$(rocket-status $mission_name)
while [ "$rocket_status" == "launching" ]
do
sleep 2
rocket_status=$(rocket-status $mission_name)
done
if [ "$rocket_status" = "failed" ]
then
rocket-debug $mission_name
fi
If you run the script, the output might be:
$ create-and-launch-rocket
failed
However, checking the exit code reveals that it remains 0:
$ echo $?
0
To address this issue, update the script so that it returns a non-zero exit code (typically 1) when the launch fails. Here is the improved version of the script:
mkdir $mission_name
rocket-add $mission_name
rocket-start-power $mission_name
rocket-internal-power $mission_name
rocket-start-sequence $mission_name
rocket-start-engine $mission_name
rocket-lift-off $mission_name
rocket_status=$(rocket-status $mission_name)
while [ "$rocket_status" == "launching" ]
do
sleep 2
rocket_status=$(rocket-status $mission_name)
done
if [ "$rocket_status" = "failed" ]
then
rocket-debug $mission_name
exit 1
fi
Now, if the rocket launch fails, the script will correctly exit with a status code of 1. This can be verified as follows:
$ create-and-launch-rocket
failed
$ echo $?
1
Best Practice
Always ensure that your scripts return an appropriate exit code. Explicitly returning a non-zero code for failure conditions facilitates better integration with other systems and scripts.
Watch Video
Watch video content
Practice Lab
Practice lab