Whenever writing a shell script, I mostly always include this option at the beginning of the script

#!/usr/bin/env bash
set -Eeuo pipefail
  • #!/usr/bin/env bash: trigger the command /usr/bin/env bash <script-path.sh>.
    The difference from using #!/bin/bash is that we do not need to know the exact place of bash in the system (it may be /bin/bash, /usr/bin/bash, or /usr/local/bin/bash, ...). Wrapping the command in an env command makes the script more portable to many environments.

Tip: if you need to add additional parameters to the invoked command, use the -S (--split-string) option of the env command.

#!/usr/bin/env -S awk -f

The -S option is not supported in every version of env, but this shouldn't be your concern because it has been supported from long ago.

  • -E or -o errtrace: Allow error traps on function calls, subshell environment, and command substitutions.

Script:

#!/usr/bin/bash env

function a {
	echo "a begins"
	false
	echo "a ends"
}

trap "echo \"ERR trap is triggered\"" ERR
echo "errtrace is on"
set -E
a
echo "errtrace is off"
set +E
a

Result:

errtrace is on
a begins
ERR trap is triggered
a ends
errtrace is off
a begins
a ends
  • -e or -o errexit: Exit immediately. When a command exits with a non-zero status, halt the script and exit with that status. By default, this option is off, bash continues the script even if an error occurs.

Script

#!/usr/bin/bash env

function a {
	echo "a begins"
	false
	echo "a ends"
}

echo "errexit is off (default)"
set +e
a
echo "errexit is on"
set -e
a

Result

errexit is off (default)
a begins
a ends
errexit is on
a begins
  • -u or -o nounset: No unset. Prevent the usage of undefined variables. By default, this option is off, bash allows the usage of undefined variables.

Script

#!/usr/bin/bash env

echo "nounset is off"
set +u
echo "unknown var's value is $unknown_var"

echo "errexit is on"
set -u
echo "unknown var's value is $unknown_var"

Result

nounset is off
unknown var's value is 
errexit is on
test.sh: line 9: unknown_var: unbound variable
  • -o pipefail: pipe failure. If any command in the pipeline chain exits with a non-zero status, the whole command will exit with that status.

Script

#!/usr/bin/bash env

echo "pipefail is on"
set -o pipefail
false | true
echo $?

echo "pipefail is off"
set +o pipefail
false | true
echo $?

Result:

pipefail is on
1
pipefail is off
0

In addition, when you want to debug the script, -x or -o xtrace might be useful. This option tells bash to print all running commands.

These options can be turn off with set +<option name>, like follows:

set +e
set +E
set +u
set +o pipefail
set +o errtrace
set +o errexit
set +o nounset
set +x
set +o xtrace

Besides, the following shopt (shell option) options are also good to be considered in several cases.

  • shopt -s nullglob: when a pattern have no match, expand them as null. By default, this option is not set and the pattern is expanded as a literal string.

Script

#!/usr/bin/bash env

cd "$(mktemp -d)"

shopt -s nullglob
echo a * b
ls * *.x

shopt -u nullglob
echo a * b
ls * *.x

cd -

Result

a b
a * b
ls: cannot access '*': No such file or directory
ls: cannot access '*.x': No such file or directory
/home/transang/tmp
  • shopt -s dotglob: include files whose names start with a dot (.) in the matching result.

Script

#!/usr/bin/bash env

cd "$(mktemp -d)"

shopt -s dotglob
touch .a
ls *

shopt -u dotglob
touch .a
ls *

rm .a
cd -

Result

.a
ls: cannot access '*': No such file or directory
/home/transang/tmp

To turn of an option with shopt, use, for example shopt -u nullglob.


Bash version used in the above sample scripts.

# bash --version
GNU bash, version 5.1.4(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Last but not least, if you are not familiar with writing bash scripts, I highly recommend using the popular shellcheck tool. Most popular editors have plugins for it.


Source:

The Set Builtin (Bash Reference Manual)
The Set Builtin (Bash Reference Manual)
The Shopt Builtin (Bash Reference Manual)
The Shopt Builtin (Bash Reference Manual)