Skip to content

Instantly share code, notes, and snippets.

@djmott
Last active January 14, 2018 11:39
Show Gist options
  • Save djmott/3e3a1f6eb3bfb01f1e5d7a8105195e89 to your computer and use it in GitHub Desktop.
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
#!/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