Bash provides a large number of options that can be used to control the behavior of bash scripts. This post examines some of the more useful ones and explains how to display which options are in use and which are not.
Exiting when an error occurs
If you want a bash script to exit soon as it encounters an error—any error at all—in your scripts, you can add the set -o errexit option. If your script contains a syntax error, tries to read a file that doesn’t exist, attempts to append to a file when you don’t have permission to do so, or misuses a command in some way, the script will end abruptly. Here is a simple example:
#!/bin/bash set -o errexit tail NoSuchFile echo -n “Enter text to be appended> “ read txt echo $txt >> NoSuchFile
Try to run this script, and you’ll see this:
$ app2file tail: NoSuchFile: No such file or directory
Because NoSuchFile doesn’t exist, the script exits, and the prompt for text to be appended to it is never run. Without the errexit setting, the script would continue running after the “No such file” error and would collect any text entered after the prompt, create the file, and add the text to it.
Tracing a bash script
Using the xtrace option, every command in a script that is run will be displayed. This option is especially useful when you are debugging a complex script. You can simply remove the xtrace option or comment out that line when you no longer need the command tracing.
#!/bin/bash set -o xtrace for day in Sun Mon Tue Wed Thu Fri Sat do echo $day sleep 2 done
The output from this script would begin like what is shown below. Lines beginning with + signs would not appear if the xtrace option were not being used.
$ loop-days-of-week + for day in Sun Mon Tue Wed Thu Fri Sat + echo Sun Sun + sleep 2 + for day in Sun Mon Tue Wed Thu Fri Sat + echo Mon Mon + sleep 2 + for day in Sun Mon Tue Wed Thu Fri Sat + echo Tue Tue …
Stopping at unbound variables
Scripts will generally ignore variables that haven’t been defined. If you use the nounset option as shown in the example below, they will exit rather than continue running.
$ cat NoSuchVar #!/bin/bash set -o nounset echo $1 echo $2 $ $ NoSuchVar 1
1 ./NoSuchVar: line 6: $2: unbound variable
Using the short form for options
It’s generally more helpful to set options in scripts using their full names as this makes the scripts more readable, but you can elect to use their short forms. For example, the xtrace option can be invoked with the command set -o xtrace as in the example shown earlier. It can, however, also be set using the simpler command set -x. Many of the bash options have single-character names like this that can be used in the “set -?” format. This information can be found in the bash man page, but the list below should make this easier.
Option Short Form ====== ========== allexport -a braceexpand -B errexit -e errtrace -E functrace -T hashall -h histexpand -H keyword -k monitor -m noclobber -C noexec -n noglob -f notify -b nounset -u onecmd -t physical -P privileged -p verbose -v xtrace -x
Display the options
To generate a list of options available with bash and whether they’re active or not, you can use the set -o command with no arguments. I used the set -o | column command on the command line to generate the output below and adjusted it lightly to make the columns line up so it would be easier to read since the column alignment was thrown off by the one lengthy option name (interactive-comments).
allexport off ignoreeof off nounset off braceexpand on interactive-comments on onecmd off emacs on keyword off physical off errexit off monitor on pipefail off errtrace off noclobber off posix off functrace off noexec off privileged off hashall on noglob off verbose off histexpand on nolog off vi off history on notify off xtrace off
Note that most of the bash options are turned off.
To see which options are enabled in a script, use the same set -o command. The script shown below will list the active options as shown above, but will also display the active options in a terse one-letter-per-option format.
#!/bin/bash set -o echo =========================== printf %s\n “$-“
Here is a sample of its output:
allexport off braceexpand on emacs off errexit off errtrace off functrace off hashall on histexpand off history off ignoreeof off interactive-comments on keyword off monitor off noclobber off noexec off noglob off nolog off notify off nounset off onecmd off physical off pipefail off posix off privileged off verbose off vi off xtrace off =========================== hB
Note that the “h” and “B” on the last line in this output reflect the status of the hashall (h) and braceexpand (B) options.
There’s a lot more to learn about how to use the options available in bash to control how scripts run. I hope this post gets you off to a good start.