Differences between revisions 6 and 7
Revision 6 as of 2015-04-07 20:57:59
Size: 2472
Editor: JarnoSuni
Comment: Some positives added. Use a simpler boolean expression in the rewriting example.
Revision 7 as of 2015-04-08 13:47:44
Size: 2777
Editor: JarnoSuni
Comment: Use shift to get unset $1
Deletions are marked like this. Additions are marked like this.
Line 13: Line 13:

 * Noticing misspelled variables is harder without set -u. Not all code of a script is necessarily executed on each run, so how would you catch all of your misspelled variables in a single run? Besides, continuing a script after the unbound variable error might be pointless.
Line 32: Line 35:
while [ "$1" ]; do # Triggers fatal error with -u while [ "$1" ]; do shift; done # Triggers fatal error with -u
Line 34: Line 37:
while [ "${1-}" ]; do # Avoids fatal error with -u while [ "${1-}" ]; do shift; done # Avoids fatal error with -u

What are the advantages and disadvantages of using set -u (or set -o nounset)?

Bash (like all other Bourne shell derivatives) has a feature activated by the command set -u (or set -o nounset). When this feature is in effect, any command which attempts to expand an unset variable will cause a fatal error (the shell immediately exits, unless it is interactive).

This feature is rather controversial, and has many extremely vocal advocates and opponents. It is designed to catch typos (misspelled variable names). However, it also triggers on many false positives, unless scripts are rewritten explicitly with set -u in mind. It is not always safe to add to the top of a script.

Positives

Advocates of set -u say the following:

  • If you write working scripts using set -u, the code works even when set +u is used. If you write scripts using set +u you are likely to write code that does not work when using set -u. Same goes for set -e, by the way.
  • Do shells generally define what is the value of an unset variable (if set +u is used)? Even if they do, you can not rely a variable is unset, even if the variable has not been set in the script; it may be set in the environment.
  • Noticing misspelled variables is harder without set -u. Not all code of a script is necessarily executed on each run, so how would you catch all of your misspelled variables in a single run? Besides, continuing a script after the unbound variable error might be pointless.

Negatives

Opponents of set -u say the following:

  • Turning this feature on breaks many scripts that do not even contain errors. There are some extremely common shell programming idioms that rely on the expansion of positional parameters (which may not be set). For example:

    while [ "$1" ]; do
      case $1 in
        -h|-?) usage;;
        --) shift; break;;
        -*) usage "Invalid option $1";;
        *) break;;
      esac
    done
  • A forced termination is a ridiculous way to handle a condition that isn't even always a real error. Why not simply print an error and move on, so you can catch all of your misspelled variables in a single run?

Rewriting scripts to deal with it

If you want to use set -u, you may have to rewrite portions of your script, to avoid having it trigger on false positives. For the most part, this involves identifying which parameter expansions should be "ignored", and protecting them with a construct such as this:

while [ "$1" ]; do shift; done         # Triggers fatal error with -u

while [ "${1-}" ]; do shift; done      # Avoids fatal error with -u

explanation for the parameter expansion

BashFAQ/112 (last edited 2023-07-08 18:56:12 by 99)