The right way to test exit codes in Bash
In this article, we’ll go over how to properly test exit codes in Bash scripts.
Testing exit codes with $?
When I first started writing Bash, I often wrote the following code to test whether a program’s execution was successful:
1some_command
2if [ "$?" -eq 0 ]; then
3 echo "It worked!"
4fi
However, this introduces complexity in the flow of the script. For example, one minor mistake like adding en echo statement:
1some_command
2echo "some_command"
3if [ "$?" -eq 0 ]; then
4 echo "It worked!"
5fi
can introduce unintended side effects that are not immediately clear. In this case, the echo
statement’s exit status is 0
and skips the if
conditional.
Therefore, if status codes are used as true/false indictators, do not use this method
Testing for successful exit codes
For the majority of my use cases, I need to evaluate whether a program’s execution is or is not successful.
Using the following syntax clearly informs readers what is happening:
1if some_command; then
2 echo "It worked!"
3fi
If some_command
executes correctly, echo "It worked!"
.
Testing for failed exit codes
Similarly, we can test for failed exit codes by negating the if
statement:
1if ! some_command; then
2 echo "It did not work!"
3fi
If some_command
executes incorrectly, echo "It did not work!"
Testing for specific exit codes
If your use case requires testing for specific exit codes, then I recommend collecting the exit status on the same line and using a case
statement.
For example:
1some_command; some_command_exit_code=$?
2case $some_command_exit_code in
3 0) echo "It worked!" ;;
4 *) echo "It did not work!" ;;
5esac
Using a case
statement allows us to control the flow in an easy-to-digest manner.
After all, code maintainability should be prioritized.