पाठ 18 / 25

Debugging, ShellCheck and Formatting

Find bugs with tracing and static analysis, and keep style consistent.

See what Bash is actually doing

Most shell bugs are about what a line expands to. bash -x script.sh or set -x inside a script prints each command after expansion, prefixed by +, so you can see exactly which arguments a command received; set +x turns tracing off. Customise the prefix with PS4, for example PS4='+ ${BASH_SOURCE##*/}:${LINENO}: ' to show file and line numbers. bash -n script.sh checks syntax without running anything. The single most valuable tool is ShellCheck, a static analyser that finds quoting bugs, unsafe rm, useless cat, read without -r, POSIX incompatibilities and many more problems, each with an explanation code (such as SC2086 for unquoted variables). Run it in your editor and in CI. shfmt formats scripts consistently. For larger scripts, bats-core provides a unit-testing framework for Bash functions and scripts.

Tracing and linting

See expansions, then let ShellCheck catch the classic mistakes.

export PS4='+ ${BASH_SOURCE##*/}:${LINENO}: '
bash -x ./deploy.sh -e staging      # trace every expanded command

# inside a script, trace only a tricky section
set -x
rsync "${rsync_args[@]}" "$src" "$dest"
set +x

bash -n deploy.sh                   # syntax check only
shellcheck deploy.sh                # e.g. SC2086: double quote to prevent globbing and word splitting
shfmt -i 4 -w deploy.sh             # format with 4-space indentation

# CI step: fail the build on ShellCheck warnings
# shellcheck --severity=warning scripts/*.sh

Make ShellCheck part of CI

ShellCheck catches in seconds the quoting bugs that otherwise surface months later on a file name with a space. Treat its warnings like compiler errors, and disable individual checks only with a comment explaining why.

त्वरित जाँच: What does `set -x` do?

  • Prints each command after expansion before running it
  • Exits on the first error
  • Makes variables read-only
  • Disables globbing
Answer

Prints each command after expansion before running it — Tracing shows the exact expanded commands, which is invaluable for debugging.