Last active
July 6, 2025 20:19
-
-
Save dotysan/4422732a09535bb062e145d8bd289b4c to your computer and use it in GitHub Desktop.
Template for writing a bash script with fancy debugging.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
# | |
# Template for writing a bash script with fancy debugging. | |
# | |
# Not yet tested at depth. Only basic handling of: | |
# - running from stdin i.e. |bash | |
# - sub-functions | |
# - sourcing of other files | |
# | |
# Pythonic asssumptions: | |
# - you have a main() worker | |
# - it can be sourced without running main() | |
# - other functions can be run by passing as args | |
# | |
DEBUG=yep | |
main() { | |
gethere # sets $HERE | |
echo 'Hello world!' | |
source "$HERE/sourceme.sh" | |
donky | |
foo | |
} | |
# ---------------------------------------------------------------------- | |
gethere() { | |
local here="${BASH_SOURCE[0]%/*}" | |
[[ $here != "${BASH_SOURCE[0]}" ]] || here=. | |
HERE=$(cd -P -- "$here" && pwd) | |
} | |
foo() { | |
source "$HERE/sourceme.sh" | |
bar | |
} | |
bar() { | |
source "$HERE/sourceme.sh" | |
} | |
# ====================================================================== | |
# shellcheck disable=SC2128 | |
if [ -z "$BASH_VERSINFO" ] || [[ ${BASH_VERSINFO[0]} -lt 4 ]] | |
then | |
echo "ERROR: Only tested on Bourne-Again SHell v4/v5." | |
exit 1 | |
fi >&2 | |
# poor man's __main__ | |
return 2>/dev/null ||: | |
if [ "$(type -t "$1")" = "function" ] | |
then | |
func="$1" | |
shift 1 | |
"$func" "$@" | |
exit 0 | |
fi | |
set -o errtrace | |
set -o errexit | |
set -o nounset | |
set -o pipefail | |
if [[ "${DEBUG:-}" ]] | |
then | |
PS4func() { | |
local normal="\033[0m" | |
#local red="\033[0;31m" | |
#local green="\033[0;32m" | |
local yellow="\033[0;33m" | |
#local blue="\033[0;34m" | |
#local magenta="\033[0;35m" | |
local cyan="\033[0;36m" | |
local i caller_idx=-1 | |
# walk the call stack to see if we are sourced and from where | |
if [[ ${#BASH_SOURCE[@]} -gt 2 ]] | |
then | |
for (( i=2; i<${#BASH_SOURCE[@]}; i++ )) | |
do | |
if [[ ${BASH_SOURCE[1]} != "${BASH_SOURCE[i]}" ]] | |
then | |
caller_idx=$i | |
break | |
fi | |
done | |
fi | |
local src func='' | |
local caller deep | |
if [[ $caller_idx -ne -1 ]] | |
then # we're in a sourced script | |
if [[ ${BASH_SOURCE[0]} == main ]] | |
then caller='<stdin>' | |
else caller="${BASH_SOURCE[0]##*/}" | |
fi | |
src="$caller:${BASH_LINENO[caller_idx-1]}${cyan}source->$yellow${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]}" | |
if [[ ${FUNCNAME[-2]} == main && ${FUNCNAME[-1]} == main ]] | |
then deep=$((${#FUNCNAME[@]}-5)) | |
else deep=$((${#FUNCNAME[@]}-4)) | |
fi | |
elif [[ ${BASH_SOURCE[0]} == main ]] | |
then # reading from standard input instead of a script file | |
src="<stdin>:${BASH_LINENO[0]}" | |
deep=$((${#FUNCNAME[@]}-1)) | |
else # a normal script file | |
src="${BASH_SOURCE[0]##*/}:${BASH_LINENO[0]}" | |
deep=$((${#FUNCNAME[@]}-2)) | |
fi | |
if (( deep >= 1 )) | |
then | |
if [[ ${FUNCNAME[1]} != source ]] | |
then func+="${FUNCNAME[1]}()" | |
fi | |
fi | |
# local lines="${BASH_LINENO[@]}" | |
# local sources="${BASH_SOURCE[@]##*/}" | |
# local funcs="${FUNCNAME[@]}" | |
# printf "${red}sources(%d): %s\nlines(%d): %s | funcs(%d): %s|%b" \ | |
# "${#BASH_SOURCE[@]}" "$sources" \ | |
# "${#BASH_LINENO[@]}" "$lines" \ | |
# "${#FUNCNAME[@]}" "$funcs" \ | |
# "$yellow$src$cyan$func$normal " | |
# run the above to debug your stacks | |
printf "%b" "$yellow$src$cyan$func$normal " | |
} | |
PS4='\r$(PS4func)' | |
set -o xtrace | |
fi | |
main "$@" | |
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
main() { | |
echo 'Hello from sourced.' | |
donky | |
} | |
donky() { | |
echo 'Hee haw.' | |
balls | |
} | |
balls() { | |
echo 'Dafuq!' | |
} | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment