Last active
January 14, 2018 11:39
-
-
Save djmott/3e3a1f6eb3bfb01f1e5d7a8105195e89 to your computer and use it in GitHub Desktop.
shell script skeleton that accepts key=value parameters and sets them as shell variables. function names that are passed in are executed in order
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 | |
set -o nounset | |
set -o errexit | |
set -o pipefail | |
set -o errtrace | |
set -o functrace | |
export _settings_names=() | |
export _settings_defaults=() | |
.main(){ | |
export _black="$(tput setaf 0)" | |
export _red="$(tput setaf 1)" | |
export _green="$(tput setaf 2)" | |
export _yellow="$(tput setaf 3)" | |
export _blue="$(tput setaf 4)" | |
export _magenta="$(tput setaf 5)" | |
export _cyan="$(tput setaf 6)" | |
export _white="$(tput setaf 7)" | |
export _reset="$(tput sgr0)" | |
export _bold="$(tput bold)" | |
export _blink="$(tput blink)" | |
export _reverse="$(tput smso)" | |
export _underline="$(tput smul)" | |
export _scriptdir="$( dirname "$( readlink -f "${BASH_SOURCE[0]}" )")" | |
export _runout=${TMP:-/tmp}/.$$.run | |
export _rootdir=${_rootdir:-$(pwd)} | |
export _scriptconf="$_scriptdir/.$(basename ${BASH_SOURCE[0]}).conf" | |
trap .on.exit EXIT | |
trap '.on.error ${LINENO} ${BASH_LINENO[@]}' ERR | |
# settings defaults | |
local _i | |
for (( _i = 0 ; _i < ${#_settings_names[@]} ; _i++ )){ | |
export ${_settings_names[_i]}="${_settings_defaults[_i]}" | |
} | |
# override default settings with config file | |
[[ -f $_scriptconf ]] && source $_scriptconf | |
# override config file with command line params | |
for param in $@ ; do | |
if [[ $param =~ .*\=.* ]]; then | |
local readonly _param_name="${param%%=*}" | |
local readonly _param_val="${param#*=}" | |
shopt -s nocasematch | |
case $_param_val in | |
yes|on|true) _param_val=1;; | |
no|off|false) _param_val=0 ;; | |
esac | |
shopt -u nocasematch | |
export ${_param_name}="${_param_val}" | |
fi | |
done | |
local _do_default=1 | |
local readonly _script_functions=$(typeset -f | awk '/ \(\) $/ {print $1}' | { grep -ve '^\.' || true; } ) | |
for param in $@; do | |
[[ $param =~ .*\=.* ]] && continue | |
for fn in ${_script_functions[@]}; do | |
if [[ $param == $fn ]]; then | |
$fn | |
continue 2 | |
fi | |
done | |
.error "Command not found: $param" | |
return 1 | |
done | |
return 0 | |
} | |
.error(){ | |
echo -e "${_red}$*${_reset}" >&2 | |
} | |
.warn(){ | |
echo -e "${_yellow}$*${_reset}" >&2 | |
} | |
.info(){ | |
echo -e "${_green}$*${_reset}" >&2 | |
} | |
.msg(){ | |
echo -e "${_reset}$*${_reset}" >&2 | |
} | |
.write.settings(){ | |
local _i | |
:>$_scriptconf | |
for (( _i = 0 ; _i < ${#_settings_names[@]} ; _i++ )){ | |
local _var=${_settings_names[_i]} | |
echo "${_var}=\"${!_var}\"" >> $_scriptconf | |
} | |
} | |
.on.exit(){ | |
local _ret=$? | |
rm -f $_runout | |
.write.settings | |
exit $_ret | |
} | |
.on.error(){ | |
local _ret=$? | |
local _line=$1 | |
shift | |
.error "Line $_line failed with $_ret" | |
.msg "Call stack:" | |
.error " $_line: $(sed -n ${_line}p $0 | awk '{gsub(/^ +| +$/,"")} {print $0}')" | |
for item in $@; do | |
[[ $item > 0 ]] && .warn " $item: $(sed -n ${item}p $0 | awk '{gsub(/^ +| +$/,"")} {print $0}')" | |
done | |
[[ -f $_runout ]] && cat $_runout | |
exit $_ret | |
} | |
.run(){ | |
local _msg="$1" | |
shift | |
echo -e "$_red COMMAND FAILED $_reset" > $_runout | |
echo -e "$_yellow $@ $_reset" >> $_runout | |
echo "" >> $_runout | |
($@) >> $_runout 2>&1 & | |
local _pid=$! | |
local _spin='-\|/' | |
local i=0 | |
while kill -0 $_pid 2>/dev/null; do | |
i=$(( (i+1) %4 )) | |
printf "\r$_yellow $_msg ${_spin:$i:1} $_reset" | |
sleep .1 | |
done | |
wait $_pid | |
rm $_runout | |
} | |
--help(){ | |
cat <<EOF | |
Usage:$_green $0 ${_magenta}<parameter=value ...> ${_cyan}<command ...> ${_reset} | |
The ${_underline}${_magenta}parameter=value${_reset} list is optional and will override settings saved in the config file. | |
Multiple parameters and commands can be passed. Commands are executed in the order given. | |
$_cyan settings $_reset - Show or set script settings | |
$_cyan debug $_reset - Start debugging the next command | |
EOF | |
} | |
-help(){ --help; } | |
help(){ --help; } | |
--?(){ --help; } | |
-?(){ --help; } | |
?(){ --help; } | |
--settings(){ | |
.msg "The following settings are defined:" | |
local _i | |
for (( _i = 0 ; _i < ${#_settings_names[@]} ; _i++ )){ | |
local readonly _var=${_settings_names[_i]} | |
printf "%25s:%s\n" "${_cyan} $_var ${_reset}" "${_magenta} ${!_var} ${_reset}" | |
} | |
} | |
-settings(){ --settings; } | |
settings(){ --settings; } | |
--setting(){ --settings; } | |
-setting(){ --settings; } | |
setting(){ --settings; } | |
--debug(){ set -x; } | |
-debug(){ --debug; } | |
debug(){ --debug; } | |
.main $@ | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment