Created
July 1, 2020 07:57
-
-
Save kesor/bbacedf4b3decafbc5bc7501b44ad9a9 to your computer and use it in GitHub Desktop.
example utils.sh
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 | |
# Common utility functions for bash scripts, | |
# - fatal -- use like `some_cmd || fatal "Some cmd failed"` | |
# - debug -- use like `debug "This is a debug message"` | |
# - timer -- use like `tm some_cmd` as a wrapper | |
# - retry -- use like `retry some_cmd` as a wrapper, retries with exp. backoff | |
# | |
# Source this bash like so: `. util.sh` | |
# | |
# *** Requires `jq` to be installed. | |
# | |
# Debug and timer is only printed when DEBUG=1 | |
# Output is printed as JSON when JSON_OUTPUT=1 | |
# | |
# echo message to stderr and exit process with non-zero return code | |
fatal() { | |
# exit process with an error message | |
# use json syntax when JSON_OUTPUT is defined | |
rc=$? | |
if [ -z "$JSON_OUTPUT" ]; then | |
echo "E $(date -u +%s%3N) ${BASH_SOURCE[1]}:${BASH_LINENO[1]}:${FUNCNAME[1]}:error:$rc: $*" >&2 | |
else | |
echo "{\"type\":\"fatal\",\"time\":\"$(date -u +%s%3N)\",\"source\":\"${BASH_SOURCE[1]}\",\"line\":\"${BASH_LINENO[1]}\",\"func\":\"${FUNCNAME[1]}\",\"code\":\"$rc\",\"message\":\"$*\"}" \ | |
| jq -Sc . >&2 | |
fi | |
exit $rc | |
} | |
# echo message to stderr when DEBUG=1 | |
debug() { | |
# print a debug message to stderr when DEBUG is defined; | |
# use json syntax when JSON_OUTPUT is defined | |
[ -z "$DEBUG" ] && return | |
if [ -z "$JSON_OUTPUT" ]; then | |
echo "D $(date -u +%s%3N) ${BASH_SOURCE[1]}:${BASH_LINENO[1]}:${FUNCNAME[1]}:debug: $*" >&2 | |
else | |
echo "{\"type\":\"debug\",\"time\":\"$(date -u +%s%3N)\",\"source\":\"${BASE_SOURCE[1]}\",\"line\":\"${BASH_LINENO[1]}\",\"func\":\"${FUNCNAME[1]}\",\"message\":\"$*\"}" \ | |
| jq -Sc . >&2 | |
fi | |
} | |
# measure time duration of executed process and echo when DEBUG=1 | |
tm() { | |
# execute a command and print its timing to stderr | |
# use json syntax when JSON_OUTPUT is defined | |
# in json format, capture the command stdout and stderr into json | |
[ -z "$DEBUG" ] && { "$@"; return $?; } | |
START=$(date +%s%3N) | |
if [ -z "$JSON_OUTPUT" ]; then | |
"$@"; rc=$? | |
END=$(date +%s%3N) | |
echo "T $(date -u +%s%3N) ${BASH_SOURCE[1]}:${BASH_LINENO[1]}:${FUNCNAME[1]}:$(( END - START ))ms: $*" >&2 | |
else | |
stdout_pipe=$(mktemp -u) | |
stderr_pipe=$(mktemp -u) | |
trap 'cat $stdout_pipe >/dev/null 2>&1; cat $stderr_pipe >/dev/null 2>&1; rm -f $stdout_pipe $stderr_pipe' RETURN | |
"$@" 1>"$stdout_pipe" 2>"$stderr_pipe"; rc=$? | |
END=$(date +%s%3N) | |
echo "{\"type\":\"time\",\"time\":\"$(date -u +%s%3N)\",\"source\":\"${BASE_SOURCE[1]}\",\"line\":\"${BASH_LINENO[1]}\",\"func\":\"${FUNCNAME[1]}\",\"ms\":\"$(( END - START ))\",\"cmd\":\"$*\"}" \ | |
| jq -Sc --arg stdout "$(cat "$stdout_pipe")" --arg stderr "$(cat "$stderr_pipe")" '. * { "stdout": $stdout, "stderr": $stderr }' >&2 | |
fi | |
return $rc | |
} | |
retry() { | |
max_retries=${MAX:-5} | |
retries=0 | |
until tm "$@" && [ "$retries" -lt "$max_retries" ]; do | |
duration=$(( 2 ** retries )) | |
retries=$(( retries + 1 )) | |
debug "Retrying after ${duration}s" | |
sleep "$duration" | |
done | |
fatal "Maximum retries ($MAX) reached. Could not perform $*" | |
} | |
# check that script is being executed by root, or abort | |
check_root() { | |
[ "$(id -u)" != '0' ] && \ | |
fatal "Must run $0 as root or using sudo." | |
} | |
# check that the docker command exists, or abort | |
check_docker() { | |
command -v docker >/dev/null \ | |
|| fatal "==> Could not find Docker installed." | |
} | |
mkdir_chown() { | |
debug "Creating directories & changing to root ownership: $*" | |
mkdir -p "$@" | |
chown -R 0:0 "$@" | |
} | |
# join multiple strings into a long string separated by first arg. value | |
strings_join() { | |
local IFS="$1" | |
shift | |
echo "$*" | |
} | |
eval_os_release() { | |
# set environment variables OS_ID and OS_VERSION_ID from Linux release info | |
## possible OS_ID values: | |
# ubuntu debian rhel centos fedora amazon | |
eval "$(sed -ne '/^\(VERSION_ID\|ID\)=/s!^!export OS_!gp' /etc/os-release)" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment