mirror of
https://github.com/natelandau/shell-scripting-templates.git
synced 2025-11-08 05:03:46 -05:00
commit 61bf734812cb62ba6e0ec224bc15f7928705a8a2 Author: Nathaniel Landau <nate@natelandau.com> Date: Thu Oct 21 15:44:21 2021 -0400 Major overhaul continued - rename templates - add checks utilities - add new array utilities - rename files - add assorted utilities - improve documentation commit 546178fff3b526f492eb0eeffc63f79537e75de3 Author: Nathaniel Landau <nate@natelandau.com> Date: Wed Oct 20 16:31:14 2021 -0400 Update conventions commit f6d0642f85518efda9c5d8472b99d1c14163e381 Author: Nathaniel Landau <nate@natelandau.com> Date: Wed Oct 20 09:47:09 2021 -0400 minor formatting changes commit 2217612b55e3f9faf803a2d0c937ea2261206505 Author: Nathaniel Landau <nate@natelandau.com> Date: Tue Oct 19 17:59:09 2021 -0400 add new functions commit 347ba7aa738dcd6a5ad9d70886b38da3a17dc89e Author: Nathaniel Landau <nate@natelandau.com> Date: Tue Oct 19 12:06:44 2021 -0400 major overhaul - Add standaloneTemplate.sh - Rework README - Refactor inline documentation - Enforce coding standards - Remove CSV utilities - Add new array utilities - add _useGNUutils_ - more ... commit cd8e0d49aef25eeaf6b3e71a3c9e1f29ab9b06f5 Author: Nathaniel Landau <nate@natelandau.com> Date: Sun Oct 17 09:56:08 2021 -0400 Add debug functions commit f7c5c0a3d19815dcc6ba80b5f5a2ebb77ef88b07 Author: Nathaniel Landau <nate@natelandau.com> Date: Sat Oct 16 21:10:01 2021 -0400 add new array functions _joinArray_, _isEmptyArray_, _sortArray_, _reverseSortArray_, and _mergearrays_ commit d8bc3d8cabdbcee3c479f97b43a45bdfe3bdafe0 Author: Nathaniel Landau <nate@natelandau.com> Date: Fri Oct 15 17:27:12 2021 -0400 add _columnize_ commit 2fd2ae9435f476bc3968c3eb0d793db4bf1d9eaf Author: Nathaniel Landau <nate@natelandau.com> Date: Mon Oct 11 22:17:45 2021 -0400 _progressBar_: Fix unbound variable commit e8933d15fc955a1acc665e9a081f131e681855d5 Author: Nathaniel Landau <nate@natelandau.com> Date: Sun Oct 10 11:50:42 2021 -0400 _alert_: header now underlined commit c9ce894361dec7d3513c038794a155519baf26bc Author: Nathaniel Landau <nate@natelandau.com> Date: Tue Oct 5 09:49:42 2021 -0400 _alert_: line numbers to gray commit 4aaddd336ce613f629a7e6a62ef3b27ffc24d22d Author: Nathaniel Landau <nate@natelandau.com> Date: Fri Oct 8 15:05:20 2021 -0400 _usage_ to stdout commit e2372fc3122ec1f20acc27f04d29b3785f014e25 Author: Nathaniel Landau <nate@natelandau.com> Date: Tue Oct 5 09:38:26 2021 -0400 _setPATH_: remove unneeded logic commit e60c75b6c954ac4bd146e2758252168027b9a43d Author: Nathaniel Landau <nate@natelandau.com> Date: Tue Oct 5 09:25:38 2021 -0400 _findSource_: bugfix commit 0e84912e1ccd7203e5beff9f8737f8374f4aa5d8 Author: Nathaniel Landau <nate@natelandau.com> Date: Thu Sep 30 16:29:25 2021 -0400 add requirements to documentation commit 2c24843e3ada591e1868a94416e40b5ac0aa4994 Author: Nathaniel Landau <nate@natelandau.com> Date: Thu Sep 30 15:34:10 2021 -0400 _uniqueFilename_: improve extension handling commit 08bc2dfdcc8632efee9179e9c960a574fc17cf0c Author: Nathaniel Landau <nate@natelandau.com> Date: Mon Sep 27 15:13:53 2021 -0400 improve hooks script commit 641918f1559d3b3aa38a9bbdf418938b2b81c176 Author: Nathaniel Landau <nate@natelandau.com> Date: Fri Sep 24 08:16:52 2021 -0400 _inArry_: case insensitivity commit eae10f170680540fdb4a1222add7e54f8785ea63 Author: Nathaniel Landau <nate@natelandau.com> Date: Mon Sep 20 18:31:44 2021 -0400 clean up alerting commit 700acd56f57fd57db84ef0e232ef41cdd7aee43c Author: Nathaniel Landau <nate@natelandau.com> Date: Mon Sep 20 18:22:11 2021 -0400 refactor _execute_ commit d893f86900a9fed9d91a0c9cc06c13b6b34d9926 Author: Nathaniel Landau <nate@natelandau.com> Date: Mon Sep 20 18:19:18 2021 -0400 'fatal' replaces 'die' commit 3326857bf127bef36cd9982246aa5b826d796d0a Author: Nathaniel Landau <nate@natelandau.com> Date: Fri Sep 17 08:29:50 2021 -0400 _execute_: ensure quiet and verbose work together
295 lines
8.6 KiB
Bash
Executable File
295 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
_mainScript_() {
|
|
# Replace everything in _mainScript_() with your script's code
|
|
header "Showing alert colors"
|
|
debug "This is debug text"
|
|
info "This is info text"
|
|
notice "This is notice text"
|
|
dryrun "This is dryrun text"
|
|
warning "This is warning text"
|
|
error "This is error text"
|
|
success "This is success text"
|
|
input "This is input text"
|
|
|
|
}
|
|
|
|
#/_mainsScript_()
|
|
|
|
# ################################## Flags and defaults
|
|
# Script specific
|
|
|
|
# # Required variables
|
|
LOGFILE="${HOME}/logs/$(basename "$0").log"
|
|
QUIET=false
|
|
LOGLEVEL=ERROR
|
|
VERBOSE=false
|
|
FORCE=false
|
|
DRYRUN=false
|
|
declare -a ARGS=()
|
|
|
|
# ################################## Functions required for this template to work
|
|
|
|
_trapCleanup_() {
|
|
# DESC:
|
|
# Log errors and cleanup from script when an error is trapped. Called by 'trap'
|
|
# ARGS:
|
|
# $1: Line number where error was trapped
|
|
# $2: Line number in function
|
|
# $3: Command executing at the time of the trap
|
|
# $4: Names of all shell functions currently in the execution call stack
|
|
# $5: Scriptname
|
|
# $6: $BASH_SOURCE
|
|
# USAGE:
|
|
# trap '_trapCleanup_ ${LINENO} ${BASH_LINENO} "${BASH_COMMAND}" "${FUNCNAME[*]}" "${0}" "${BASH_SOURCE[0]}"' EXIT INT TERM SIGINT SIGQUIT SIGTERM ERR
|
|
# OUTS:
|
|
# Exits script with error code 1
|
|
|
|
local _line=${1:-} # LINENO
|
|
local _linecallfunc=${2:-}
|
|
local _command="${3:-}"
|
|
local _funcstack="${4:-}"
|
|
local _script="${5:-}"
|
|
local _sourced="${6:-}"
|
|
|
|
if [[ "$(declare -f "fatal")" && "$(declare -f "_printFuncStack_")" ]]; then
|
|
_funcstack="'$(echo "${_funcstack}" | sed -E 's/ / < /g')'"
|
|
if [[ ${_script##*/} == "${_sourced##*/}" ]]; then
|
|
fatal "${7:-} command: '${_command}' (line: ${_line}) [func: $(_printFuncStack_)]"
|
|
else
|
|
fatal "${7:-} command: '${_command}' (func: ${_funcstack} called at line ${_linecallfunc} of '${_script##*/}') (line: ${_line} of '${_sourced##*/}') "
|
|
fi
|
|
else
|
|
printf "%s\n" "Fatal error trapped. Exiting..."
|
|
fi
|
|
|
|
if [ "$(declare -f "_safeExit_")" ]; then
|
|
_safeExit_ 1
|
|
else
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
_sourceUtilities_() {
|
|
# DESC:
|
|
# Sources bash utility functions
|
|
# ARGS:
|
|
# $1 (required): Directories or files containing utility functions
|
|
# OUTS:
|
|
# 0 if success
|
|
# 1 if failure
|
|
# USAGE:
|
|
# _sourceHelperFiles_ "/path/to/dir" "path/to/file.sh"
|
|
|
|
local _filesSourced=true
|
|
|
|
[[ $# == 0 ]] && _filesSourced=false
|
|
|
|
local _fileToSource
|
|
local _location
|
|
if [ ${_filesSourced} == true ]; then
|
|
for _location in "$@"; do
|
|
if [[ -d ${_location} ]]; then
|
|
for _fileToSource in "${_location}"/*.{sh,bash}; do
|
|
if [[ -f ${_fileToSource} ]]; then
|
|
if ! source "${_fileToSource}"; then
|
|
_filesSourced=false
|
|
break 2
|
|
fi
|
|
else
|
|
_filesSourced=false
|
|
break 2
|
|
fi
|
|
done
|
|
elif [[ -f ${_location} ]] && [[ ${_location} =~ .*\.(sh|bash)$ ]]; then
|
|
if ! source "${_fileToSource}"; then
|
|
_filesSourced=false
|
|
break
|
|
fi
|
|
else
|
|
_filesSourced=false
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ ${_filesSourced} == true ]; then
|
|
return 0
|
|
else
|
|
printf "%s\n" "ERROR: Invalid argument to ${FUNCNAME[0]}: ${_location}"
|
|
if [ "$(declare -f "_safeExit_")" ]; then
|
|
_safeExit_ 1
|
|
else
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
}
|
|
|
|
_parseOptions_() {
|
|
# DESC:
|
|
# Iterates through options passed to script and sets variables. Will break -ab into -a -b
|
|
# when needed and --foo=bar into --foo bar
|
|
# ARGS:
|
|
# $@ from command line
|
|
# OUTS:
|
|
# Sets array 'ARGS' containing all arguments passed to script that were not parsed as options
|
|
# USAGE:
|
|
# _parseOptions_ "$@"
|
|
|
|
# Iterate over options
|
|
local _optstring=h
|
|
declare -a _options
|
|
local _c
|
|
local i
|
|
while (($#)); do
|
|
case $1 in
|
|
# If option is of type -ab
|
|
-[!-]?*)
|
|
# Loop over each character starting with the second
|
|
for ((i = 1; i < ${#1}; i++)); do
|
|
_c=${1:i:1}
|
|
_options+=("-${_c}") # Add current char to options
|
|
# If option takes a required argument, and it's not the last char make
|
|
# the rest of the string its argument
|
|
if [[ ${_optstring} == *"${_c}:"* && ${1:i+1} ]]; then
|
|
_options+=("${1:i+1}")
|
|
break
|
|
fi
|
|
done
|
|
;;
|
|
# If option is of type --foo=bar
|
|
--?*=*) _options+=("${1%%=*}" "${1#*=}") ;;
|
|
# add --endopts for --
|
|
--) _options+=(--endopts) ;;
|
|
# Otherwise, nothing special
|
|
*) _options+=("$1") ;;
|
|
esac
|
|
shift
|
|
done
|
|
set -- "${_options[@]:-}"
|
|
unset _options
|
|
|
|
# Read the options and set stuff
|
|
while [[ ${1:-} == -?* ]]; do
|
|
case $1 in
|
|
# Custom options
|
|
|
|
# Common options
|
|
-h | --help)
|
|
_usage_
|
|
_safeExit_
|
|
;;
|
|
--loglevel)
|
|
shift
|
|
LOGLEVEL=${1}
|
|
;;
|
|
--logfile)
|
|
shift
|
|
LOGFILE="${1}"
|
|
;;
|
|
-n | --dryrun) DRYRUN=true ;;
|
|
-v | --verbose) VERBOSE=true ;;
|
|
-q | --quiet) QUIET=true ;;
|
|
--force) FORCE=true ;;
|
|
--endopts)
|
|
shift
|
|
break
|
|
;;
|
|
*)
|
|
if [ "$(declare -f "_safeExit_")" ]; then
|
|
fatal "invalid option: $1"
|
|
else
|
|
printf "%s\n" "Invalid option: $1"
|
|
exit 1
|
|
fi
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
ARGS+=("$@") # Store the remaining user input as arguments.
|
|
}
|
|
|
|
_usage_() {
|
|
cat <<USAGE_TEXT
|
|
|
|
${bold}$(basename "$0") [OPTION]... [FILE]...${reset}
|
|
|
|
This is a script template. Edit this description to print help to users.
|
|
|
|
${bold}Options:${reset}
|
|
-h, --help Display this help and exit
|
|
--loglevel [LEVEL] One of: FATAL, ERROR, WARN, INFO, NOTICE, DEBUG, ALL, OFF
|
|
(Default is 'ERROR')
|
|
--logfile [FILE] Full PATH to logfile. (Default is '${HOME}/logs/$(basename "$0").log')
|
|
-n, --dryrun Non-destructive. Makes no permanent changes.
|
|
-q, --quiet Quiet (no output)
|
|
-v, --verbose Output more information. (Items echoed to 'verbose')
|
|
--force Skip all user interaction. Implied 'Yes' to all actions.
|
|
|
|
${bold}Example Usage:${reset}
|
|
|
|
${gray}# Run the script and specify log level and log file.${reset}
|
|
$(basename "$0") -vn --logfile "/path/to/file.log" --loglevel 'WARN'
|
|
USAGE_TEXT
|
|
}
|
|
|
|
# ################################## INITIALIZE AND RUN THE SCRIPT
|
|
# (Comment or uncomment the lines below to customize script behavior)
|
|
|
|
trap '_trapCleanup_ ${LINENO} ${BASH_LINENO} "${BASH_COMMAND}" "${FUNCNAME[*]}" "${0}" "${BASH_SOURCE[0]}"' EXIT INT TERM SIGINT SIGQUIT SIGTERM
|
|
|
|
# Trap errors in subshells and functions
|
|
set -o errtrace
|
|
|
|
# Exit on error. Append '||true' if you expect an error
|
|
set -o errexit
|
|
|
|
# Use last non-zero exit code in a pipeline
|
|
set -o pipefail
|
|
|
|
# Confirm we have BASH greater than v4
|
|
[ "${BASH_VERSINFO:-0}" -ge 4 ] || {
|
|
printf "%s\n" "ERROR: BASH_VERSINFO is '${BASH_VERSINFO:-0}'. This script requires BASH v4 or greater."
|
|
exit 1
|
|
}
|
|
|
|
# Make `for f in *.txt` work when `*.txt` matches zero files
|
|
shopt -s nullglob globstar
|
|
|
|
# Set IFS to preferred implementation
|
|
IFS=$' \n\t'
|
|
|
|
# Run in debug mode
|
|
# set -o xtrace
|
|
|
|
# Source utility functions
|
|
_sourceUtilities_ "${HOME}/repos/shell-scripting-templates/utilities"
|
|
|
|
# Initialize color constants
|
|
_setColors_
|
|
|
|
# Disallow expansion of unset variables
|
|
set -o nounset
|
|
|
|
# Force arguments when invoking the script
|
|
# [[ $# -eq 0 ]] && _parseOptions_ "-h"
|
|
|
|
# Parse arguments passed to script
|
|
_parseOptions_ "$@"
|
|
|
|
# Create a temp directory '$TMP_DIR'
|
|
# _makeTempDir_ "$(basename "$0")"
|
|
|
|
# Acquire script lock
|
|
# _acquireScriptLock_
|
|
|
|
# Source GNU utilities for use on MacOS
|
|
# _useGNUutils_
|
|
|
|
# Run the main logic script
|
|
_mainScript_
|
|
|
|
# Exit cleanly
|
|
_safeExit_
|