Skip to content

Instantly share code, notes, and snippets.

@zerolagtime
Last active March 19, 2021 13:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zerolagtime/69667bb0f6f794238026826f063cde67 to your computer and use it in GitHub Desktop.
Save zerolagtime/69667bb0f6f794238026826f063cde67 to your computer and use it in GitHub Desktop.
BASH Shell Script Skeleton Template
#!/bin/bash
# This is a template script that has built-in logging
# with colored messages. It also supports command line parsing.
usage() {
echo "$0 [-h | --help] [-v | --verbose]"
echo " [-q | --quiet] [-w str | --with-parameter=str]"
echo " [--noisy]"
echo "Here is the reason this script exists."
echo "Where:"
echo "--with-parameter is an option that has a parameter"
echo "--help will display this help message"
echo "--verbose will show all debug messages"
echo "--quiet will only show warning or error messages"
echo "--noisy gives extremely detailed debug logs with"
echo " every command shown"
exit 1
}
main() {
# This is your main function. Command line parameters
# that can be parsed have been. Remaining parameters are in $*
# Return the exit code of your choice
log_info "our informational message"
log_info "Our additional parameters to the program are: $@"
log_warn "False alarm - WITH_OPT is set to $WITH_OPT (use --with-parameter)"
subroutine1 some value "with spaces" || return 1
random_failure || return $?
return 0
}
subroutine1() {
for val in "$@"; do
log_debug "passed a subroutine a parameter: \"$val\""
done
log_info "the subroutine works"
return 0
}
random_failure() {
log_info "This function will randomly fail and should result in the program exiting"
if [ $(($RANDOM % 2)) == 0 ]; then
log_error "Random failure"
return 4
else
log_info "Whew! We got away."
fi
return 0
}
#####################################################################
# No program code below this line
# Only set up command line options and environment variable defaults
LOG_LEVEL=info
declare -A LEVELS=( [error]=0 [warn]=1 [info]=2 [debug]=3 [noisy]=4)
if [ -t 1 ]; then # -t is "am stdout a terminal?"
ESC=$(printf "\E")
RED="${ESC}[31m"
YELLOW="${ESC}[33m"
CYAN="${ESC}[36m"
GREEN="${ESC}[32m"
RESET="${ESC}[0m"
else
ESC=''
RED=''
YELLOW=''
CYAN=''
GREEN=''
RESET=''
fi
__log() {
level=$1
if [ ${LEVELS[$level]} -gt ${LEVELS[$LOG_LEVEL]} ]; then
# the log level is to restrictive, so don't show
return
fi
shift
msg="$*"
preamble=""
if [ "$LOG_LEVEL" == "debug" ]; then
preamble="[$(date)][${FUNCNAME[2]}] "
fi
case $level in
error) echo "$preamble${RED}ERROR${RESET}: $msg" 1>&2 ;;
warn) echo "$preamble${YELLOW}WARN${RESET}: $msg" 1>&2 ;;
info) echo "$preamble${CYAN}INFO${RESET}: $msg" ;;
debug) echo "$preamble${GREEN}DEBUG${RESET}: $msg" ;;
esac
}
log_debug() {
if [ $# -gt 0 ]; then
__log debug "$@"
else
while read line; do __log debug "$line"; done
fi
}
log_info() {
if [ $# -gt 0 ]; then
__log info "$@"
else
while read line; do __log info "$line"; done
fi
}
log_warn() {
if [ $# -gt 0 ]; then
__log warn "$@"
else
while read line; do __log warn "$line"; done
fi
}
log_error() {
if [ $# -gt 0 ]; then
__log error "$@"
else
while read line; do __log error "$line"; done
fi
}
SHORT=hvw:q
LONG=help,verbose,with-parameter:,quiet,vv,very-verbose,noisy
OPTS=$(getopt --options $SHORT --long $LONG --name "$0" -- "$@")
[ $? -eq 0 ] || {
echo "Incorrect options provided"
usage
exit 1
}
cd "$(dirname $0)"
# initialize any defaults here
WITH_OPT=default
eval set -- "$OPTS"
while true; do
case "$1" in
-w | --with-parameter)
# sanitize WITH_OPT
WITH_OPT="${2//[;\/\\|]/}"
shift 2
;;
-v | --verbose)
LOG_LEVEL=debug
shift
;;
-q | --quiet)
LOG_LEVEL=warn
shift
;;
-h | --help)
usage
shift
;;
--vv | --very-verbose | --noisy)
LOG_LEVEL=noisy
# inspiration from https://wiki.bash-hackers.org/scripting/debuggingtips
log_error() { :
}
log_warn() { :
}
log_info() { :
}
log_debug() { :
}
__log() { :
};
export PS4='[$(date)][${BASH_SOURCE}:${LINENO}] ${FUNCNAME[1]:+${FUNCNAME[1]}(): }'
shift
;;
--)
shift
break
;;
esac
done
# Allow strings to have exclamation points in them
set +o histexpand
if [ "$LOG_LEVEL" == "noisy" ]; then
# note that PS4 is set to do all of the dumping
set -o xtrace
fi
# Uncomment this section if the user was expected to run this as root
#
# verify any command line parameters here
#if [ $UID != "0" ]; then
# log_error "This command should be run as root. Rerunning with sudo."
# sudo bash -c "$@"
# exit $?
#fi
# Uncomment this section and document the essential commands if
# this script will be broken without access to these tools.
# Include commands outside of a typical busybox minimalist system.
#
#log_debug "Ensuring that essential commands are in the PATH"
#for essential_command in ansible ssh; do
# if [ -z "$(command -v $essential_command)" ]; then
# log_error "An essential command is missing: $essential_command"
# exit 2
# fi
#done
cd $(dirname $(command -v $0))
here=$(pwd)
log_debug "Starting main function of $0"
main "$@"
err=$?
if [ $err -ne 0 ]; then
log_error "Completed main function of $0 with errors. Exiting with error code $err."
else
log_debug "Completed main function of $0. Exiting with error code $err."
fi
exit $err
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment