mirror of
https://github.com/natelandau/shell-scripting-templates.git
synced 2025-11-14 16:03:47 -05:00
Squashed commit of the following:
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
This commit is contained in:
@@ -17,7 +17,7 @@ _mainScript_() {
|
||||
STOP_WORD_FILE="${HOME}/.git_stop_words"
|
||||
GIT_DIFF_TEMP="${TMP_DIR}/diff.txt"
|
||||
|
||||
if cat "${STOP_WORD_FILE}" | grep . | grep -v '# ' >"${TMP_DIR}/pattern_file.txt"; then
|
||||
if [ -f "${STOP_WORD_FILE}" ]; then
|
||||
|
||||
if [[ $(basename "${STOP_WORD_FILE}") == "$(basename "${1}")" ]]; then
|
||||
debug "Don't check stop words file for stop words. Skipping $(basename "${1}")"
|
||||
@@ -25,16 +25,18 @@ _mainScript_() {
|
||||
fi
|
||||
debug "Checking for stop words"
|
||||
|
||||
# remove blank lines and comments from stopwords file
|
||||
# remove blank lines from stopwords file
|
||||
cat "${STOP_WORD_FILE}" | sed '/^$/d' >"${TMP_DIR}/pattern_file.txt"
|
||||
|
||||
# Add diff to a temporary file
|
||||
git diff --cached -- "${1}" | grep '^+' >"${GIT_DIFF_TEMP}"
|
||||
git diff --cached -- "${1}" | grep '^+' >"${GIT_DIFF_TEMP}"
|
||||
|
||||
if grep --file="${TMP_DIR}/pattern_file.txt" "${GIT_DIFF_TEMP}"; then
|
||||
error "Found git stop word in '$(basename "${1}")'"
|
||||
_safeExit_ 1
|
||||
fi
|
||||
else
|
||||
debug "Could not find git stopwords file expected at '${STOP_WORD_FILE}'. Or it was empty. Continuing..."
|
||||
debug "Could not find git stopwords file expected at '${STOP_WORD_FILE}'. Continuing..."
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -87,26 +89,35 @@ _mainScript_() {
|
||||
error "Error in ${1}"
|
||||
_safeExit_ 1
|
||||
else
|
||||
success "yaml-lint passed: '${1}'"
|
||||
success "yaml-lint passed: '${1}'"
|
||||
fi
|
||||
elif command -v yamllint >/dev/null; then
|
||||
debug "Linting YAML File"
|
||||
if ! yamllint "${1}"; then
|
||||
error "Error in ${1}"
|
||||
_safeExit_ 1
|
||||
else
|
||||
if [ -f "$(git rev-parse --show-toplevel)/.yamllint.yml" ]; then
|
||||
if ! yamllint -c "$(git rev-parse --show-toplevel)/.yamllint.yml" "${1}"; then
|
||||
error "YAML Error in ${1}"
|
||||
_safeExit_ 1
|
||||
else
|
||||
success "yamllint passed: '${1}'"
|
||||
fi
|
||||
else
|
||||
if ! yamllint "${1}"; then
|
||||
error "YAML Error in ${1}"
|
||||
_safeExit_ 1
|
||||
else
|
||||
success "yamllint passed: '${1}'"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
notice "No YAML linter installed. Continuing..."
|
||||
notice "No YAML linter installed. Continuiing..."
|
||||
fi
|
||||
}
|
||||
|
||||
_lintShellscripts_() {
|
||||
if command -v shellcheck >/dev/null; then
|
||||
debug "Linting shellscript: ${1}"
|
||||
if ! shellcheck --exclude=2016,2059,2001,2002,2148,1090,2162,2005,2034,2154,2086,2155,2181,2164,2120,2119,1083,1117,2207 "${1}"; then
|
||||
error "Error in ${file}"
|
||||
if ! shellcheck --exclude=2016,2059,2001,2002,2148,1090,2162,2005,2034,2154,2086,2155,2181,2164,2120,2119,1083,1117,2207,1091 "${1}"; then
|
||||
error "Error in ${1}"
|
||||
_safeExit_ 1
|
||||
else
|
||||
success "shellcheck passed: '${1}'"
|
||||
@@ -133,7 +144,47 @@ _mainScript_() {
|
||||
unset filename
|
||||
}
|
||||
|
||||
_lintAnsible_() {
|
||||
|
||||
if ! command -v ansible-lint >/dev/null; then
|
||||
notice "Found Ansible files but ansible-lint is not available. Continuing..."
|
||||
return 0
|
||||
elif [[ "$(basename ${1})" =~ (^\.|^requirements|j2|vault\.yml|variables|meta|defaults?|inventory) ]]; then
|
||||
# Don't lint files that are not Ansible playbooks
|
||||
debug "won't ansible lint: ${1}"
|
||||
return 0
|
||||
elif [[ ${1} =~ /(handlers|vars/|defaults/|meta/|molecule/|templates/|files/)/ ]]; then
|
||||
# Don't lint in directory names that are not likely to contain Ansible playbooks
|
||||
debug "Won't ansible lint: ${1}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
ANSIBLE_COMMAND="ansible-lint -vv --parseable-severity"
|
||||
if [ -f "$(git rev-parse --show-toplevel)/.ansible-lint.yml" ]; then
|
||||
ANSIBLE_COMMAND="ansible-lint -p -c $(git rev-parse --show-toplevel)/.ansible-lint.yml"
|
||||
fi
|
||||
|
||||
debug "Linting ansible file: ${1}"
|
||||
if ! ${ANSIBLE_COMMAND} "${1}"; then
|
||||
error "Ansible-lint error"
|
||||
_safeExit_ 1
|
||||
else
|
||||
success "ansible-lint passed: ${1}"
|
||||
fi
|
||||
}
|
||||
|
||||
# RUN SCRIPT LOGIC
|
||||
|
||||
# Attempt to discern if we are working on an repo that contains ansible files
|
||||
IS_ANSIBLE_REPO=false
|
||||
if find "$(git rev-parse --show-toplevel)" -type f -mindepth 1 -maxdepth 1 \
|
||||
-name "inventory.yml" \
|
||||
-o -name "ansible.cfg" \
|
||||
-o -name ".ansible-lint.yml" &>/dev/null; then
|
||||
|
||||
IS_ANSIBLE_REPO=true
|
||||
fi
|
||||
|
||||
_ignoreSymlinks_
|
||||
|
||||
while read -r STAGED_FILE; do
|
||||
@@ -142,17 +193,18 @@ _mainScript_() {
|
||||
|
||||
_gitStopWords_ "${STAGED_FILE}"
|
||||
|
||||
if [[ "${STAGED_FILE}" =~ \.(yaml|yml)$ ]]; then
|
||||
if [[ ${STAGED_FILE} =~ \.(yaml|yml)$ ]]; then
|
||||
_lintYAML_ "${STAGED_FILE}"
|
||||
if [ "${IS_ANSIBLE_REPO}" = true ]; then
|
||||
_lintAnsible_ "${STAGED_FILE}"
|
||||
fi
|
||||
fi
|
||||
if [[ "${STAGED_FILE}" =~ \.(bash|sh)$ ]]; then
|
||||
if [[ ${STAGED_FILE} =~ \.(bash|sh)$ || "$(head -n 1 "${STAGED_FILE}")" =~ ^#!.*bash$ ]]; then
|
||||
_lintShellscripts_ "${STAGED_FILE}"
|
||||
fi
|
||||
if [[ "${STAGED_FILE}" =~ \.(sh|bash|bats|zsh)$ ]]; then
|
||||
if [[ ${STAGED_FILE} =~ \.(sh|bash|bats|zsh)$ || "$(head -n 1 "${STAGED_FILE}")" =~ ^#!.*bash$ ]]; then
|
||||
_BATS_ "${STAGED_FILE}"
|
||||
fi
|
||||
else
|
||||
fatal "${STAGED_FILE} does not exist"
|
||||
fi
|
||||
|
||||
done < <(git diff --cached --name-only --line-prefix="$(git rev-parse --show-toplevel)/")
|
||||
@@ -160,22 +212,22 @@ _mainScript_() {
|
||||
} # end _mainScript_
|
||||
|
||||
# ################################## Flags and defaults
|
||||
# Script specific
|
||||
# Script specific
|
||||
|
||||
# Common
|
||||
LOGFILE="${HOME}/logs/$(basename "$0").log"
|
||||
QUIET=false
|
||||
LOGLEVEL=ERROR
|
||||
VERBOSE=false
|
||||
FORCE=false
|
||||
DRYRUN=false
|
||||
declare -a ARGS=()
|
||||
NOW=$(LC_ALL=C date +"%m-%d-%Y %r") # Returns: 06-14-2015 10:34:40 PM
|
||||
DATESTAMP=$(LC_ALL=C date +%Y-%m-%d) # Returns: 2015-06-14
|
||||
HOURSTAMP=$(LC_ALL=C date +%r) # Returns: 10:34:40 PM
|
||||
TIMESTAMP=$(LC_ALL=C date +%Y%m%d_%H%M%S) # Returns: 20150614_223440
|
||||
LONGDATE=$(LC_ALL=C date +"%a, %d %b %Y %H:%M:%S %z") # Returns: Sun, 10 Jan 2016 20:47:53 -0500
|
||||
GMTDATE=$(LC_ALL=C date -u -R | sed 's/\+0000/GMT/') # Returns: Wed, 13 Jan 2016 15:55:29 GMT
|
||||
# Common
|
||||
LOGFILE="${HOME}/logs/$(basename "$0").log"
|
||||
QUIET=false
|
||||
LOGLEVEL=ERROR
|
||||
VERBOSE=false
|
||||
FORCE=false
|
||||
DRYRUN=false
|
||||
declare -a ARGS=()
|
||||
NOW=$(LC_ALL=C date +"%m-%d-%Y %r") # Returns: 06-14-2015 10:34:40 PM
|
||||
DATESTAMP=$(LC_ALL=C date +%Y-%m-%d) # Returns: 2015-06-14
|
||||
HOURSTAMP=$(LC_ALL=C date +%r) # Returns: 10:34:40 PM
|
||||
TIMESTAMP=$(LC_ALL=C date +%Y%m%d_%H%M%S) # Returns: 20150614_223440
|
||||
LONGDATE=$(LC_ALL=C date +"%a, %d %b %Y %H:%M:%S %z") # Returns: Sun, 10 Jan 2016 20:47:53 -0500
|
||||
GMTDATE=$(LC_ALL=C date -u -R | sed 's/\+0000/GMT/') # Returns: Wed, 13 Jan 2016 15:55:29 GMT
|
||||
|
||||
# ################################## Custom utility functions
|
||||
_setPATH_() {
|
||||
@@ -190,37 +242,65 @@ _setPATH_() {
|
||||
done
|
||||
|
||||
for NEWPATH in "${NEWPATHS[@]}"; do
|
||||
if ! echo "$PATH" | grep -Eq "(^|:)${NEWPATH}($|:)"; then
|
||||
PATH="${NEWPATH}:${PATH}"
|
||||
debug "Added '${tan}${NEWPATH}${purple}' to PATH"
|
||||
if [ -d "${NEWPATH}" ]; then
|
||||
if ! echo "${PATH}" | grep -Eq "(^|:)${NEWPATH}($|:)"; then
|
||||
PATH="${NEWPATH}:${PATH}"
|
||||
debug "Added '${NEWPATH}' to PATH"
|
||||
else
|
||||
debug "_setPATH_: '${NEWPATH}' already exists in PATH"
|
||||
fi
|
||||
else
|
||||
debug "_setPATH_: can not find: ${NEWPATH}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
# ################################## Common Functions for script template
|
||||
# Colors
|
||||
if tput setaf 1 &>/dev/null; then
|
||||
bold=$(tput bold)
|
||||
white=$(tput setaf 7)
|
||||
reset=$(tput sgr0)
|
||||
purple=$(tput setaf 171)
|
||||
red=$(tput setaf 1)
|
||||
green=$(tput setaf 76)
|
||||
tan=$(tput setaf 3)
|
||||
yellow=$(tput setaf 3)
|
||||
blue=$(tput setaf 38)
|
||||
underline=$(tput sgr 0 1)
|
||||
else
|
||||
bold="\033[4;37m"
|
||||
white="\033[0;37m"
|
||||
reset="\033[0m"
|
||||
purple="\033[0;35m"
|
||||
red="\033[0;31m"
|
||||
green="\033[1;32m"
|
||||
tan="\033[0;33m"
|
||||
yellow="\033[0;33m"
|
||||
blue="\033[0;34m"
|
||||
underline="\033[4;37m"
|
||||
fi
|
||||
_setColors_() {
|
||||
# DESC: Sets colors use for alerts.
|
||||
# ARGS: None
|
||||
# OUTS: None
|
||||
# USAGE: echo "${blue}Some text${reset}"
|
||||
|
||||
if tput setaf 1 &>/dev/null; then
|
||||
bold=$(tput bold)
|
||||
underline=$(tput smul)
|
||||
reverse=$(tput rev)
|
||||
reset=$(tput sgr0)
|
||||
|
||||
if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then
|
||||
white=$(tput setaf 231)
|
||||
blue=$(tput setaf 38)
|
||||
yellow=$(tput setaf 11)
|
||||
tan=$(tput setaf 3)
|
||||
green=$(tput setaf 82)
|
||||
red=$(tput setaf 1)
|
||||
purple=$(tput setaf 171)
|
||||
gray=$(tput setaf 250)
|
||||
else
|
||||
white=$(tput setaf 7)
|
||||
blue=$(tput setaf 38)
|
||||
yellow=$(tput setaf 3)
|
||||
tan=$(tput setaf 3)
|
||||
green=$(tput setaf 2)
|
||||
red=$(tput setaf 1)
|
||||
purple=$(tput setaf 13)
|
||||
gray=$(tput setaf 7)
|
||||
fi
|
||||
else
|
||||
bold="\033[4;37m"
|
||||
reset="\033[0m"
|
||||
underline="\033[4;37m"
|
||||
reverse=""
|
||||
white="\033[0;37m"
|
||||
blue="\033[0;34m"
|
||||
yellow="\033[0;33m"
|
||||
tan="\033[0;33m"
|
||||
green="\033[1;32m"
|
||||
red="\033[0;31m"
|
||||
purple="\033[0;35m"
|
||||
gray="\033[0;37m"
|
||||
fi
|
||||
}
|
||||
|
||||
_alert_() {
|
||||
# DESC: Controls all printing of messages to log files and stdout.
|
||||
@@ -237,28 +317,32 @@ _alert_() {
|
||||
local function_name color
|
||||
local alertType="${1}"
|
||||
local message="${2}"
|
||||
local line="${3:-}" # Optional line number
|
||||
local line="${3:-}" # Optional line number
|
||||
|
||||
if [[ -n "${line}" && "${alertType}" =~ ^(fatal|error) && "${FUNCNAME[2]}" != "_trapCleanup_" ]]; then
|
||||
if [[ -n ${line} && ${alertType} =~ ^(fatal|error) && ${FUNCNAME[2]} != "_trapCleanup_" ]]; then
|
||||
message="${message} (line: ${line}) $(_functionStack_)"
|
||||
elif [[ -n "${line}" && "${FUNCNAME[2]}" != "_trapCleanup_" ]]; then
|
||||
elif [[ -n ${line} && ${FUNCNAME[2]} != "_trapCleanup_" ]]; then
|
||||
message="${message} (line: ${line})"
|
||||
elif [[ -z "${line}" && "${alertType}" =~ ^(fatal|error) && "${FUNCNAME[2]}" != "_trapCleanup_" ]]; then
|
||||
elif [[ -z ${line} && ${alertType} =~ ^(fatal|error) && ${FUNCNAME[2]} != "_trapCleanup_" ]]; then
|
||||
message="${message} $(_functionStack_)"
|
||||
fi
|
||||
|
||||
if [[ "${alertType}" =~ ^(error|fatal) ]]; then
|
||||
if [[ ${alertType} =~ ^(error|fatal) ]]; then
|
||||
color="${bold}${red}"
|
||||
elif [ "${alertType}" = "warning" ]; then
|
||||
elif [ "${alertType}" == "info" ]; then
|
||||
color="${gray}"
|
||||
elif [ "${alertType}" == "warning" ]; then
|
||||
color="${red}"
|
||||
elif [ "${alertType}" = "success" ]; then
|
||||
elif [ "${alertType}" == "success" ]; then
|
||||
color="${green}"
|
||||
elif [ "${alertType}" = "debug" ]; then
|
||||
elif [ "${alertType}" == "debug" ]; then
|
||||
color="${purple}"
|
||||
elif [ "${alertType}" = "header" ]; then
|
||||
elif [ "${alertType}" == "header" ]; then
|
||||
color="${bold}${tan}"
|
||||
elif [[ "${alertType}" =~ ^(input|notice) ]]; then
|
||||
elif [ ${alertType} == "notice" ]; then
|
||||
color="${bold}"
|
||||
elif [ ${alertType} == "input" ]; then
|
||||
color="${bold}${underline}"
|
||||
elif [ "${alertType}" = "dryrun" ]; then
|
||||
color="${blue}"
|
||||
else
|
||||
@@ -268,7 +352,7 @@ _alert_() {
|
||||
_writeToScreen_() {
|
||||
|
||||
("${QUIET}") && return 0 # Print to console when script is not 'quiet'
|
||||
[[ ${VERBOSE} == false && "${alertType}" =~ ^(debug|verbose) ]] && return 0
|
||||
[[ ${VERBOSE} == false && ${alertType} =~ ^(debug|verbose) ]] && return 0
|
||||
|
||||
if ! [[ -t 1 ]]; then # Don't use colors on non-recognized terminals
|
||||
color=""
|
||||
@@ -280,11 +364,13 @@ _alert_() {
|
||||
_writeToScreen_
|
||||
|
||||
_writeToLog_() {
|
||||
[[ "${alertType}" == "input" ]] && return 0
|
||||
[[ "${LOGLEVEL}" =~ (off|OFF|Off) ]] && return 0
|
||||
[ -z "${LOGFILE:-}" ] && LOGFILE="$(pwd)/$(basename "$0").log"
|
||||
[ ! -d "$(dirname "${LOGFILE}")" ] && command mkdir -p "$(dirname "${LOGFILE}")"
|
||||
[[ ! -f "${LOGFILE}" ]] && touch "${LOGFILE}"
|
||||
[[ ${alertType} == "input" ]] && return 0
|
||||
[[ ${LOGLEVEL} =~ (off|OFF|Off) ]] && return 0
|
||||
if [ -z "${LOGFILE:-}" ]; then
|
||||
LOGFILE="$(pwd)/$(basename "$0").log"
|
||||
fi
|
||||
[ ! -d "$(dirname "${LOGFILE}")" ] && mkdir -p "$(dirname "${LOGFILE}")"
|
||||
[[ ! -f ${LOGFILE} ]] && touch "${LOGFILE}"
|
||||
|
||||
# Don't use colors in logs
|
||||
if command -v gsed &>/dev/null; then
|
||||
@@ -304,22 +390,27 @@ _alert_() {
|
||||
_writeToLog_
|
||||
;;
|
||||
INFO | info | Info)
|
||||
if [[ "${alertType}" =~ ^(die|error|fatal|warning|info|notice|success) ]]; then
|
||||
if [[ ${alertType} =~ ^(error|fatal|warning|info|notice|success) ]]; then
|
||||
_writeToLog_
|
||||
fi
|
||||
;;
|
||||
NOTICE | notice | Notice)
|
||||
if [[ ${alertType} =~ ^(error|fatal|warning|notice|success) ]]; then
|
||||
_writeToLog_
|
||||
fi
|
||||
;;
|
||||
WARN | warn | Warn)
|
||||
if [[ "${alertType}" =~ ^(die|error|fatal|warning) ]]; then
|
||||
if [[ ${alertType} =~ ^(error|fatal|warning) ]]; then
|
||||
_writeToLog_
|
||||
fi
|
||||
;;
|
||||
ERROR | error | Error)
|
||||
if [[ "${alertType}" =~ ^(die|error|fatal) ]]; then
|
||||
if [[ ${alertType} =~ ^(error|fatal) ]]; then
|
||||
_writeToLog_
|
||||
fi
|
||||
;;
|
||||
FATAL | fatal | Fatal)
|
||||
if [[ "${alertType}" =~ ^(die|fatal) ]]; then
|
||||
if [[ ${alertType} =~ ^fatal ]]; then
|
||||
_writeToLog_
|
||||
fi
|
||||
;;
|
||||
@@ -327,7 +418,7 @@ _alert_() {
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
if [[ "${alertType}" =~ ^(die|error|fatal) ]]; then
|
||||
if [[ ${alertType} =~ ^(error|fatal) ]]; then
|
||||
_writeToLog_
|
||||
fi
|
||||
;;
|
||||
@@ -343,23 +434,35 @@ success() { _alert_ success "${1}" "${2:-}"; }
|
||||
dryrun() { _alert_ dryrun "${1}" "${2:-}"; }
|
||||
input() { _alert_ input "${1}" "${2:-}"; }
|
||||
header() { _alert_ header "== ${1} ==" "${2:-}"; }
|
||||
die() {
|
||||
_alert_ fatal "${1}" "${2:-}"
|
||||
_safeExit_ "1"
|
||||
}
|
||||
debug() { _alert_ debug "${1}" "${2:-}"; }
|
||||
fatal() {
|
||||
_alert_ fatal "${1}" "${2:-}"
|
||||
_safeExit_ "1"
|
||||
}
|
||||
debug() { _alert_ debug "${1}" "${2:-}"; }
|
||||
verbose() { _alert_ debug "${1}" "${2:-}"; }
|
||||
|
||||
_functionStack_() {
|
||||
# DESC: Prints the function stack in use
|
||||
# ARGS: None
|
||||
# OUTS: Prints [function]:[file]:[line]
|
||||
# NOTE: Does not print functions from the alert class
|
||||
local _i
|
||||
funcStackResponse=()
|
||||
for ((_i = 1; _i < ${#BASH_SOURCE[@]}; _i++)); do
|
||||
case "${FUNCNAME[$_i]}" in "_alert_" | "_trapCleanup_" | fatal | error | warning | notice | info | debug | dryrun | header | success) continue ;; esac
|
||||
funcStackResponse+=("${FUNCNAME[$_i]}:$(basename ${BASH_SOURCE[$_i]}):${BASH_LINENO[_i - 1]}")
|
||||
done
|
||||
printf "( "
|
||||
printf %s "${funcStackResponse[0]}"
|
||||
printf ' < %s' "${funcStackResponse[@]:1}"
|
||||
printf ' )\n'
|
||||
}
|
||||
|
||||
_safeExit_() {
|
||||
# DESC: Cleanup and exit from a script
|
||||
# ARGS: $1 (optional) - Exit code (defaults to 0)
|
||||
# OUTS: None
|
||||
|
||||
if [[ -d "${SCRIPT_LOCK:-}" ]]; then
|
||||
if [[ -d ${SCRIPT_LOCK:-} ]]; then
|
||||
if command rm -rf "${SCRIPT_LOCK}"; then
|
||||
debug "Removing script lock"
|
||||
else
|
||||
@@ -367,7 +470,7 @@ _safeExit_() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${TMP_DIR:-}" && -d "${TMP_DIR:-}" ]]; then
|
||||
if [[ -n ${TMP_DIR:-} && -d ${TMP_DIR:-} ]]; then
|
||||
if [[ ${1:-} == 1 && -n "$(ls "${TMP_DIR}")" ]]; then
|
||||
# Do something here to save TMP_DIR on a non-zero script exit for debugging
|
||||
command rm -r "${TMP_DIR}"
|
||||
@@ -401,7 +504,7 @@ _trapCleanup_() {
|
||||
|
||||
funcstack="'$(echo "$funcstack" | sed -E 's/ / < /g')'"
|
||||
|
||||
if [[ "${script##*/}" == "${sourced##*/}" ]]; then
|
||||
if [[ ${script##*/} == "${sourced##*/}" ]]; then
|
||||
fatal "${7:-} command: '${command}' (line: ${line}) [func: $(_functionStack_)]"
|
||||
else
|
||||
fatal "${7:-} command: '${command}' (func: ${funcstack} called at line ${linecallfunc} of '${script##*/}') (line: $line of '${sourced##*/}') "
|
||||
@@ -454,23 +557,6 @@ _acquireScriptLock_() {
|
||||
fi
|
||||
}
|
||||
|
||||
_functionStack_() {
|
||||
# DESC: Prints the function stack in use
|
||||
# ARGS: None
|
||||
# OUTS: Prints [function]:[file]:[line]
|
||||
# NOTE: Does not print functions from the alert class
|
||||
local _i
|
||||
funcStackResponse=()
|
||||
for ((_i = 1; _i < ${#BASH_SOURCE[@]}; _i++)); do
|
||||
case "${FUNCNAME[$_i]}" in "_alert_" | "_trapCleanup_" | fatal | error | warning | notice | info | verbose | debug | dryrun | header | success | die) continue ;; esac
|
||||
funcStackResponse+=("${FUNCNAME[$_i]}:$(basename ${BASH_SOURCE[$_i]}):${BASH_LINENO[$_i - 1]}")
|
||||
done
|
||||
printf "( "
|
||||
printf %s "${funcStackResponse[0]}"
|
||||
printf ' < %s' "${funcStackResponse[@]:1}"
|
||||
printf ' )\n'
|
||||
}
|
||||
|
||||
_parseOptions_() {
|
||||
# Iterate over options
|
||||
# breaking -ab into -a -b when needed and --foo=bar into --foo bar
|
||||
@@ -547,7 +633,8 @@ _usage_() {
|
||||
|
||||
${bold}Options:${reset}
|
||||
-h, --help Display this help and exit
|
||||
--loglevel [LEVEL] One of: FATAL, ERROR, WARN, INFO, DEBUG, ALL, OFF (Default is 'ERROR')
|
||||
--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)
|
||||
@@ -563,18 +650,46 @@ EOF
|
||||
# ################################## 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
|
||||
set -o errtrace # Trap errors in subshells and functions
|
||||
set -o errexit # Exit on error. Append '||true' if you expect an error
|
||||
set -o pipefail # Use last non-zero exit code in a pipeline
|
||||
# shopt -s nullglob globstar # Make `for f in *.txt` work when `*.txt` matches zero files
|
||||
IFS=$' \n\t' # Set IFS to preferred implementation
|
||||
# set -o xtrace # Run in debug mode
|
||||
set -o nounset # Disallow expansion of unset variables
|
||||
# [[ $# -eq 0 ]] && _parseOptions_ "-h" # Force arguments when invoking the script
|
||||
_parseOptions_ "$@" # Parse arguments passed to script
|
||||
_makeTempDir_ "$(basename "$0")" # Create a temp directory '$TMP_DIR'
|
||||
# _acquireScriptLock_ # Acquire script lock
|
||||
_mainScript_ # Run the main logic script
|
||||
_safeExit_ # Exit cleanly
|
||||
trap '_trapCleanup_ ${LINENO} ${BASH_LINENO} "${BASH_COMMAND}" "${FUNCNAME[*]}" "${0}" "${BASH_SOURCE[0]}"' EXIT INT TERM SIGINT SIGQUIT
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# 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_
|
||||
|
||||
# Run the main logic script
|
||||
_mainScript_
|
||||
|
||||
# Exit cleanly
|
||||
_safeExit_
|
||||
|
||||
Reference in New Issue
Block a user