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.

Video

Further reading and video