Frequently Asked Question
How do I debug a shell script with set -x?
set -x (also known as xtrace) tells bash to print every command to standard error
just before it runs it, with all variables and command substitutions expanded. Add it
to the top of a script with set -x (often together with set -euo pipefail), or
switch it on for a section by writing set -x and then set +x later. You can also
enable tracing without editing the script by invoking it as bash -x ./myscript.sh.
Each traced line is prefixed by the value of $PS4, by default a single +, and you
can customise that prefix to show the line number and function: export PS4='+ ${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]:-main}: ' gives a much more informative
trace.
set -x is enough to debug 90% of bash problems on its own. When a script does
something surprising, turning on the trace immediately shows you what the shell
thought you meant: which variables were empty, which globs expanded to nothing, which
branch of the if was actually taken. For more interactive debugging there is bashdb
(rare, but exists) and for one-off probes you can sprinkle echo "DEBUG: x=$x" >&2
lines, but set -x is the workhorse. Pair it with ShellCheck before runtime and
set -e for clear failure, and you have a complete bash diagnostic toolkit.