Created
September 23, 2021 01:35
-
-
Save zerolagtime/a6d985fecae4b29e91d03d3b4dd20a85 to your computer and use it in GitHub Desktop.
Bash skeleton - supports colored output for WARN and ERROR
This file contains 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
$ ./script-template.sh --noisy | |
[[[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:200] command -v /tmp/script-template.sh | |
[[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:200] dirname /tmp/script-template.sh | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:200] cd /tmp | |
[[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:201] pwd | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:201] here=/tmp | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:202] log_debug 'Starting main function of /tmp/script-template.sh' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:159] main(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:203] main | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:24] main(): log_info 'our informational message' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:157] main(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:25] main(): log_info 'Our additional parameters to the program are: ' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:157] main(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:26] main(): log_warn 'False alarm - WITH_OPT is set to default (use --with-parameter)' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:155] main(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:27] main(): subroutine1 some value 'with spaces' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:32] main(): for val in "$@" | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:33] main(): log_debug 'passed a subroutine a parameter: "some"' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:159] subroutine1(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:32] main(): for val in "$@" | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:33] main(): log_debug 'passed a subroutine a parameter: "value"' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:159] subroutine1(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:32] main(): for val in "$@" | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:33] main(): log_debug 'passed a subroutine a parameter: "with spaces"' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:159] subroutine1(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:35] main(): log_info 'the subroutine works' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:157] subroutine1(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:36] main(): return 0 | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:28] main(): random_failure | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:39] main(): log_info 'This function will randomly fail and should result in the program exiting' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:157] random_failure(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:40] main(): '[' 0 == 0 ']' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:41] main(): log_error 'Random failure' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:153] random_failure(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:42] main(): return 4 | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:28] main(): return 4 | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:204] err=4 | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:205] '[' 4 -ne 0 ']' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:206] log_error 'Completed main function of /tmp/script-template.sh with errors. Exiting with error code 4.' | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:153] main(): : | |
[Wed 22 Sep 2021 09:32:21 PM EDT][/tmp/script-template.sh:210] exit 4 |
This file contains 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
$ ./script-template.sh | |
INFO: our informational message | |
INFO: Our additional parameters to the program are: | |
WARN: False alarm - WITH_OPT is set to default (use --with-parameter) | |
INFO: the subroutine works | |
INFO: This function will randomly fail and should result in the program exiting | |
INFO: Whew! We got away. |
This file contains 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
$ ./script-template.sh -v | more | |
[Thu Mar 18 17:01:12 EDT 2021][main] DEBUG: Starting main function of ./script-template.sh | |
[Thu Mar 18 17:01:12 EDT 2021][main] INFO: our informational message | |
[Thu Mar 18 17:01:12 EDT 2021][main] INFO: Our additional parameters to the program are: | |
[Thu Mar 18 17:01:12 EDT 2021][main] WARN: False alarm - WITH_OPT is set to default (use --with-parameter) | |
[Thu Mar 18 17:01:12 EDT 2021][subroutine1] DEBUG: passed a subroutine a parameter: "some" | |
[Thu Mar 18 17:01:12 EDT 2021][subroutine1] DEBUG: passed a subroutine a parameter: "value" | |
[Thu Mar 18 17:01:12 EDT 2021][subroutine1] DEBUG: passed a subroutine a parameter: "with spaces" | |
[Thu Mar 18 17:01:12 EDT 2021][subroutine1] INFO: the subroutine works | |
[Thu Mar 18 17:01:12 EDT 2021][random_failure] INFO: This function will randomly fail and should result in the program exiting | |
[Thu Mar 18 17:01:12 EDT 2021][random_failure] ERROR: Random failure | |
[Thu Mar 18 17:01:12 EDT 2021][main] ERROR: Completed main function of ./script-template.sh with errors. Exiting with error code 4. |
This file contains 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
$ ./script-template.sh -v | more | |
[Thu Mar 18 17:01:09 EDT 2021][main] DEBUG: Starting main function of ./script-template.sh | |
[Thu Mar 18 17:01:09 EDT 2021][main] INFO: our informational message | |
[Thu Mar 18 17:01:09 EDT 2021][main] INFO: Our additional parameters to the program are: | |
[Thu Mar 18 17:01:09 EDT 2021][main] WARN: False alarm - WITH_OPT is set to default (use --with-parameter) | |
[Thu Mar 18 17:01:09 EDT 2021][subroutine1] DEBUG: passed a subroutine a parameter: "some" | |
[Thu Mar 18 17:01:09 EDT 2021][subroutine1] DEBUG: passed a subroutine a parameter: "value" | |
[Thu Mar 18 17:01:09 EDT 2021][subroutine1] DEBUG: passed a subroutine a parameter: "with spaces" | |
[Thu Mar 18 17:01:09 EDT 2021][subroutine1] INFO: the subroutine works | |
[Thu Mar 18 17:01:09 EDT 2021][random_failure] INFO: This function will randomly fail and should result in the program exiting | |
[Thu Mar 18 17:01:09 EDT 2021][random_failure] INFO: Whew! We got away. | |
[Thu Mar 18 17:01:09 EDT 2021][main] DEBUG: Completed main function of ./script-template.sh. Exiting with error code 0. |
This file contains 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
#!/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