Everything You Need To Know About Exit Codes in Bash!
Most of the developers can’t tell the difference between SIGKILL, SIGTERM, and SIGINT!
If you have worked with Bash before, you would agree that writing robust bash scripts is not an easy feat, specially when the script you write executes in uncertain environment. The commands that constitute the script may fail because of factors out of our control.
Employing ‘Exit Codes’ to catch and handle these errors is one easy way of making our Bash script more resilient.
The exit code is an integer value returned by a Bash command or script upon its termination. These codes indicate the outcome of the program’s execution.
Generally, a non-zero exit code indicates unsuccessful execution of a program while an exit code of 0 denotes a successfully executed program.
The value of exit codes can range from 0 to 255 and some of these values hold special meaning and are more prominent than others. In this blog, we will be exploring these special exit codes and how we can use them to write more resilient bash scripts.
How do I check the exit code for a command?
Let’s explore how to access and utilise exit codes now that we understand what they are.
Bash provides a special variable $?
(the dollar question-mark) that stores the exit code received from the most recently executed command or script.
~ echo 'Hello World!'
Hello World!
~ echo $?
0
~ ls alien.txt
ls: alien.txt: No such file or directory
~ echo $?
1
~ cat profile
cat: profile: No such file or directory
~ echo $?
1
Bash does not maintain a history of exit codes and only provides access to the exit code of the last executed command. Therefore, if exit codes of older commands is needed, they should be stored to a variable!
🏃 Try running some commands on your own and experience the different exit codes it returns.
Did you find an exit code other than 0 or 1? Read-on to understand what different exit-code values mean!
What does different exit code values mean?
The simplest of all the cases is the exit code 0. It means that the command was executed successfully. Any value other than zero indicates some issue because of which the command couldn’t run to completion.
There are some prominent non-zero exit codes that hold special meaning to them. Let us explore them one-by-one.
Exit Code 1
An exit code of 1 is used to denote a generic execution error. It can also be used to denote an impermissible operation.
~ let a='1/0'
zsh: division by zero
~ echo $?
1
Exit Code 2
The system returns this exit code when it encounters a syntax error in the command, including incorrect use of arguments.
Appearance of exit code 2 suggests that the command could not execute because of incorrect syntax usage.
~ grep --p temp.txt
grep: unrecognized option `--p'
usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
~ echo $?
2
Exit Code 126
If you get exit code 126, it means you’re trying to run a program you’re not allowed to.
~ touch tmp.sh
~ ./tmp.sh
zsh: permission denied: ./tmp.sh
~ echo $?
126
It’s important to note that exit code 126 specifically indicates insufficient permissions to execute a script or command. This differs from a general “Permission Denied” error, which can occur for other reasons, such as read/write access issues.
Exit Code 127
When an unknown command is executed in Bash, an exit code of 127 is returned. For example, if I were to run the tmp.sh
file without specifying the path, Bash will not be able to find the command and will return an exit code of 127.
~ tmp.sh
zsh: command not found: tmp.sh
~ echo $?
127
Exit Code Series 128+n
If an application or command crashes or is forcefully stopped because of a serious error, you’ll see an exit code that’s 128 plus a signal number (128+n). The “n” represents specific termination signals like SIGTERM or SIGKILL, which indicate how the program was shut down.
Let us look at some of the significant exit codes from this series ~
SIGINT (Exit Code 130) — When a program is terminated by termination signal 2 (n=2), we receive an exit code of 130 (128+2). The termination signal 2 is also known as SIGINT (Signal for Keyboard Interruption).
SIGKILL (Exit Code 137) — When a process is killed by sending a kill signal (n=9), we get an exit code of 137.
SIGTERM (Exit Code 143) — SIGTERM stands for Signal to Terminate and has a signal value of 15 (n=15). This is the default behaviour when a process is killed without specifying arguments.
What happens when a program returns an exit code greater than 255?
While modern versions of Bash can handle exit codes larger than 255, older versions have a limit. Any code above 255 gets wrapped around, essentially starting back at 0.
To avoid compatibility problems with older systems or scripts, it’s best to stick with exit codes between 0 and 255.
With this we reach the end of this blog. If you enjoyed reading this piece, consider clicking the ❤️ button and leaving a comment below!