Often enough shellscripts are the quickest solution to a given problem. However, writing shellscripts is just as hard as using any other programming language, as for example Valve (or rather Steam users) found out the hard way.

However, there are options you can set to make your shellscripts safer, which others have elaborated on already very nicely, therefore we will not look at it in detail here but instead recommend to take a look there. Just briefly, these options summarize to set -eEuo pipefail and make your script terminate on the first command exiting non-zero (including non-zero-exiting commands within a pipe chain) and when you try to use unset variables if set at the beginning of your shellscript. The aforementioned error in the steam-uninstall-script would have been prevented by this.

However, you will have to set these options in every single script. You could put them into your .bashrc, for example, but not all scripts out there and on your system might be written with this option set in mind. As adding these options into every single of your scripts might sound tedious, there is a better solution: writing a shell that is safe by default!

Implementing a safe bash

To do so we recognize that most scripts nowadays start with a line starting with the shebang: #!/path/to/interpreter. In the case of bash this is typically #!/bin/bash.

To be able to simply invoke a safebash instead of bash at this point, create a file /usr/local/bin/safebash containing


# exit immediately when a command fails
set -e

# abort on attempting to use an undefined variable (hello Valve! :))
set -u

# set exitcode of a pipe chain to the exit code of the rightmost
# command not exiting with zero, if there are any
# in combination with -e this aborts on failure within a pipe chain
set -o pipefail

# make functions inherit ERR-traps, so that they fire when set -e takes effect there
set -E

# let subshells inherit these options

bash "$@"

and make it executable with chmod +x /usr/local/bin/safebash

You can now start your shellscript-file with #!/usr/local/bin/safebash instead of #!/bin/bash and all the aforementioned options will be active without specifying anything explicitly.