Writing defensive Bash scripts
From ben.goodacre.name/tech
Any kind of script should be written to expect the unexpected, this is known as programming defensively.
Contents |
Exit on error
set -o errexit
The script will exit if any statement returns a non-zero exit code. Ensure that no statement or command returns a non-zero exit code as part of its normal operation as this option could cause the script to break where it might otherwise have worked.
Exit on use of missing variable
set -o nounset
The script will exit if any statement attempts to refer to a missing variable. Commands can have very-undesired affects if a variable returns, consider rm -Rf $var/etc/apache2.
Using $?
The $? environment variable will not work if set -o errexit is set as BASH will exit on the line before. The following can be used as an alternative:
/bin/command || { echo "error";exit 1; }
Expect for files to be missing
mkdir -p /path/to/dir rm -f file
Create parent folders if they do not exist and do not return a non-zero value if files do not exist with rm.
Always use quotes around variables
Otherwise a space will cause statements using it fail usually.
Be prepared for the script to be killed or otherwise exit early
The trap command allows a command or sub to be run upon the script receiving a signal. There are many signals that can be trapped but three most useful are:
| Signal | Case |
| INT | Interupt - user presses Ctrl+C |
| TERM | Terminate - user kills the script using kill |
| EXIT | Triggered when the script exits normally or from a condition using the set command. |
To clear up temp files upon exiting normally or abnormally:
trap "rm -f /tmp/file; exit" INT TERM EXIT command1 command2 trap - INT TERM EXIT
Different traps can be configured by specifiying the signals in separate commands.