Good Practices in bash scripts
Shebang (#!)
It is called a shebang or a “bang” line. It is nothing but the absolute path to the Bash interpreter. It consists of a number sign and an exclamation point character (#!), followed by the full path to the interpreter such as /bin/bash. All scripts under Linux execute using the interpreter specified on a first line. This ensures that the correct interpreter will be used to interpret the script, even if it is executed under another shell.
set -e
this will make the shell script exit as soon as any line in the bash script fails. for example, a shell file like below will execute every line
arun@home:~$ ./set_e_without.sh
true
true
false
true
After adding set -e, it will stop executing after the line that fails, in this case the one that returns false.
arun@home:~$ ./with_set_e.sh
true
true
Ignore failure in scripts
if we don’t want the script to fail after certain failing statements, we can append these certain statements with || true.
arun@home:~$ ./with_set_e_and_ignore_fail.sh
true
true
failing foo was ignored
true
set -x
this will make the shell print each line before execution. Combining this with previous set statement and same example, it will look like
arun@home:~$ ./with_set_x.sh
++ true
++ echo true
true
++ true
++ echo true
true
++ false
set -u
The following example has variable b which is not set. The run of the script will be successful.
arun@home:~$ ./without_set_u.sh
++ a=0
++ echo 0
0
++ echo 0
0
++ echo
++ echo 0
0
But adding -u to the same script will force bash to treat unset variables as an error and exit immediately.
arun@home:~$ ./with_set_u.sh
++ a=0
++ echo 0
0
++ echo 0
0
./with_set_u.sh: line 5: b: unbound variable
set -o pipefail
bash usually looks at the exit code of the last command in a pipeline. This can cause a problem for -e option as it will only consider the leftmost command’s exit code in a pipeline. This particular option sets the exit code of pipeline commands to that of the rightmost command to exit with a non-zero status or 0 if all exit successfully.
arun@home:~$ ./without_pipefail.sh
./test.sh: line 3: a: unbound variable
++ echo 'pipe chain failed'
pipe chain failed
++ echo 'but I execute'
but I execute
arun@home:~$ ./with_pipefail.sh
./test.sh: line 3: a: unbound variable
++ echo 'pipe chain failed'
pipe chain failed
arun@home:~$ echo $?
1
the echo $? is a special variable in bash that shows the exit code of last run command.