Another article from the series of notes to self which others might find useful 😉

Recently I was trying to run some complex build scripts that produce our unified installers inside a docker container, and I was running into issues with missing dependencies (i.e. commands). Unfortunately not all the scripts were written using unofficial bash strict mode or even just with set -e and set -o pipefail enabled which means I only saw some “command not found” errors flash quickly past, get ignored and get lost in the long output.

To make it work I needed to find what were the missing commands and add appropriate packages to the docker image.

However the idea of scrolling through the horrendously long output to try to dig out all the bash: command not found errors to get all the missing commands didn’t seem too exciting, so I wondered if there’s a way to use bash’s command-not-found hook to essentially get notified of those as they happen and write them out to a file.

Well, it turns out there is, here’s what I came up with:

# Place this at the top of the top-level script to get a file with
# details of every missing command of that script and any child bash
# scripts.
function command_not_found_handle() {
  echo "{source: \"${BASH_SOURCE[1]}\", line: ${BASH_LINENO[0]}, exe: \"${1}\", command: \"$*\"}" >> /tmp/missing-commands.log
  echo "${BASH_SOURCE[1]}: line ${BASH_LINENO[0]}: ${1}: command not found (cmd: $*)"
  return 127
export -f command_not_found_handle

After running the build script again, I got a /tmp/missing-commands.log file with a list of all missing command executables and full command lines that would have been invoked.

As a side-note, if you write any bash and haven’t heard about the unofficial bash strict mode (or one of its adaptations like 1 or 2) check it out, it’s a bit of a pain to get used to at first (read “Issues & Solutions” and 2) but pays off massively by exposing problems early (almost like compilers for sane languages 😉).

Leave a comment

Your email address will not be published. Required fields are marked *