Last active
December 15, 2024 19:54
-
-
Save zerolagtime/69667bb0f6f794238026826f063cde67 to your computer and use it in GitHub Desktop.
BASH Shell Script Skeleton Template
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
#!/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