Statements: Zero cost debugging
I like to sprinkle my code with tracing functions for runtime debugging, which might look something like this:
#! /usr/bin/env bash
log_debug()
{
if [ -v VERBOSE ]
then
printf "log: %s\n" "$*" >&2
fi
}
debug_info()
{
printf "hello\n"
}
log_debug $(debug_info)
printf "done\n"
So normally it would print only “done”, but if you set the environment variable
VERBOSE
it prints
log: hello
done
The function call for log_debug
is obviously always performed. But since this
is a shell script, debug_info
is also executed. That is regardless of VERBOSE
being set or not. This slows my scripts down somewhat, even when I am not
requesting debugging output.
There is a way to fix this without restructuring the code and it uses a macro again:
#! /usr/bin/env bash
log_debug()
{
printf "log: %s\n" "$*" >&2
}
# remove old aliases, which might do unexpected stuff
# enable aliases in script
unalias -a
shopt -s expand_aliases
# Turn a previously defined log_debug function into a harmless ':' builtin
# function which does nothing and comment out the rest of the arguments.
# Without the ':' placing a log_debug in an otherwise empty function would
# fail.
if [ -v VERBOSE ]
then
alias log_debug=': #'
fi
debug_info()
{
printf "hello\n"
}
log_debug `debug_info`
printf "done\n"
This can be tricky to pull off though as the alias expansion happens as the script is read by bash and not when the line gets executed.
#! /usr/bin/env bash
log_debug()
{
printf "log: %s\n" "$*" >&2
}
# Remove old aliases, which might do unexpected stuff.
unalias -a
# Enable aliases in script.
shopt -s expand_aliases
debug_info()
{
log_debug "hello"
}
# too late, the log_debug in debug_info() has already been expanded
alias log_debug=': #'
debug_info
Another pitfall are continuations. The comment in the expanded alias swallows
the continuation character \
and the second line is left intact.
#! /usr/bin/env bash
alias log_debug=': #'
call_me()
{
log_debug "first line \
second line"
}
call_me
The same caveat applies to other multi-line statements. So this technique takes some care to execute properly.