-
-
Save disaac/fe963fd3d3c7c4a460b7271b062d0aba to your computer and use it in GitHub Desktop.
A template bash script based on google style guide with some little improvements
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 | |
# Here short description of this script | |
# This is just a template to be used for writing new bash scripts | |
### | |
# Based on Google Style Guide: https://google.github.io/styleguide/shell.xml | |
# General remarks | |
# * Executables should have no extension (strongly preferred) or a .sh extension. | |
# * Libraries must have a .sh extension and should not be executable | |
# * SUID and SGID are forbidden on shell scripts. | |
# * All error messages should go to STDERR. | |
# * Write todos like this: # TODO(renzok): Handle the unlikely edge cases (bug ####) | |
# * Indent 2 spaces. No tabs. 80 chars max per line | |
# * Put ; do and ; then on the same line as the while, for or if. | |
# * Quoting: https://google.github.io/styleguide/shell.xml#Quoting | |
# * Function Names: Lower-case, with underscores to separate words. | |
# ** Separate libraries with ::. Parentheses are required after the function name. | |
# * prefer shell builtin over separate process | |
## | |
## | |
# Coding tips and tricks: | |
# http://stackoverflow.com/questions/1167746/how-to-assign-a-heredoc-value-to-a-variable-in-bash | |
# | |
# Exit immediately if a command exits with a non-zero status. | |
# | |
# This might cause problems e.g. using read to read a heredoc cause | |
# read to always return non-zero set -o errexit Treat unset variables | |
# as an error when substituting. | |
set -o nounset | |
# 1. section: global constants (all words upper case separated by underscore) | |
# declare -r CONSTANT_VARIABLE='value' | |
declare -r TMP_FILE_PREFIX=${TMPDIR:-/tmp}/prog.$$ | |
#declare -r colblk='\033[0;30m' # Black - Regular | |
declare -r COLOR_RED='\033[0;31m' # Red | |
declare -r COLOR_GREEN='\033[0;32m' # Green | |
declare -r COLOR_YELLOW='\033[0;33m' # Yellow | |
declare -r COLOR_PURPLE='\033[0;35m' # Purple | |
declare -r COLOR_GRAY='\033[0;90m' # Dark Gray | |
declare -r COLOR_RESET='\033[0m' # Text Reset | |
declare verbosity=6 | |
### verbosity levels | |
declare -ri LEVEL_SILENT=0 | |
declare -ri LEVEL_CRITICAL=1 | |
declare -ri LEVEL_ERROR=2 | |
declare -ri LEVEL_WARN=3 | |
# also for success=ok log message | |
declare -ri LEVEL_NOTIFY=4 | |
declare -ri LEVEL_INFO=5 | |
declare -ri LEVEL_DEBUG=6 | |
# as per discussion | |
# http://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself | |
# but use BASH_SOURCE[0] | |
declare -r SCRIPTPATH=$( cd $(dirname ${BASH_SOURCE[0]}) > /dev/null; pwd -P ) | |
# 2. section: functions | |
# Part of a package/library | |
function mypackage::my_func() { | |
} | |
## esilent prints output even in silent mode | |
function log::silent () { verb_lvl=$LEVEL_SILENT log "$@" ;} | |
function log::critical () { verb_lvl=$LEVEL_CRITICAL log "${COLOR_PURPLE}FATAL${COLOR_RESET} --- ${*}" ;} | |
function log::error () { verb_lvl=$LEVEL_ERROR log "${COLOR_RED}ERROR${COLOR_RESET} --- ${*}" ;} | |
function log::warn () { verb_lvl=$LEVEL_WARN log "${COLOR_YELLOW}WARNING${COLOR_RESET} - ${*}" ;} | |
function log::notify () { verb_lvl=$LEVEL_NOTIFY log "${*}" ;} | |
function log::ok () { verb_lvl=$LEVEL_NOTIFY log "SUCCESS - ${*}" ;} | |
function log::info () { verb_lvl=$LEVEL_INFO log "${COLOR_GRAY}INFO${COLOR_RESET} ---- ${*}" ;} | |
function log::debug () { verb_lvl=$LEVEL_DEBUG log "${COLOR_GREEN}DEBUG${COLOR_RESET} --- ${*}" ;} | |
function log::dumpvar () { for var in "$@" ; do log::debug "$var=${!var}" ; done } | |
function log() { | |
if [ $verbosity -ge $verb_lvl ]; then | |
datestring=$(date +"%Y-%m-%d %H:%M:%S") | |
echo -e "$datestring - ${*}" | |
fi | |
} | |
# all progs need to be given as parameters | |
# e.g. _check_required_programs md5 xsltproc | |
function intern::check_required_programs() { | |
# Required program(s) | |
#req_progs=(readlink date md5) | |
for p in ${@}; do | |
hash "${p}" 2>&- || \ | |
{ echo >&2 " Required program \"${p}\" not installed or in search PATH."; | |
exit 1; | |
} | |
done | |
} | |
function cleanup() { | |
rm -f ${TMP_FILE_PREFIX}.* | |
echo "always implement this" && exit 100 | |
} | |
function usage() { | |
cat <<EOF | |
Usage: $0 | |
TODO | |
EOF | |
} | |
# Single function | |
function main() { | |
# the optional parameters string starting with ':' for silent errors snd h for help usage | |
local -r OPTS=':h' | |
while builtin getopts ${OPTS} opt "${@}"; do | |
case $opt in | |
h) usage ; exit 0 | |
;; | |
\?) | |
echo ${opt} ${OPTIND} 'is an invalid option' >&2; | |
usage; | |
exit ${INVALID_OPTION} | |
;; | |
:) | |
echo 'required argument not found for option -'${OPTARG} >&2; | |
usage; | |
exit ${INVALID_OPTION} | |
;; | |
*) echo "Too many options. Can not happen actually :)" | |
;; | |
esac | |
done | |
log::silent "Silent message" | |
log::critical "CRITICAL MESSAGE!" | |
log::error "this is an error" | |
log::warn "this is a warning" | |
log::ok "super ok" | |
log::info "this is an information" | |
log::debug "debugging" | |
# testing dumpvar function | |
TEST=test log::dumpvar TEST | |
cleanup | |
exit 0 | |
} | |
# Always check return values and give informative return values. | |
# see https://google.github.io/styleguide/shell.xml#Checking_Return_Values | |
# set a trap for (calling) cleanup all stuff before process | |
# termination by SIGHUBs | |
trap "cleanup; exit 1" 1 2 3 13 15 | |
# this is the main executable function at end of script | |
main "$@" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment