Wiki
* Scroll me *
PREFACE
About Wiki
GOLANG
Snippets
Pitfalls
Development
Production
SHELL
Shell Script
NETWORKING
Networking
KUBERNETES
Commands
Patterns
Potholes
ISTIO
Istio
VAULT
Vault
INFRA AS CODE
Terraform
Pulumi
Shell Script
Table of Contents
Robust Shell Scripts
First of all, if your script is over 100 lines, it should probably be rewritten in Python or Go.
Bash Options
Always do set -o errexit -o pipefail -o nounset
at the start of the script.
-o errexit
: Abort when a command exits with non-zero status (except in until, while, if)-o pipefail
: Causes a pipeline to return the exit status of the last command in the pipe that returned a non-zero return value.-o nounset
: Attempt to use undefined variable causes an error and forces an exit
Trapping Deferred Calls
1
2
3
trap '{
rm -f '"${TEMP_FILE}" "${LOCK_FILE}"'
}' INT TERM EXIT
INT
: capturing SIGINT (Interrupt). ctrl-c sends such a signal.TERM
: capturing SIGTERM (Terminate).EXIT
is a pseudo-signal triggered when the script exits, either through reaching the end of the script, anexit
command, or a failing command whenset -o errexit
.
Just Quote Everything
Variable expansion:
- Good:
"$my_var"
- Bad:
$my_var
Command substitution:
- Good:
"$(cmd)"
- Bad:
$(cmd)
Linter and Formatter
- Use shellcheck, a shell script static analysis tool, to improve your script.
- Use shfmt to format your script
Further Reading
Bash Pitfalls: a compilation of common mistakes made by bash users.
Snippets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# log interpolates and writes message to stderr with timestamp.
log() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}
# Retry a command up to a specific numer of times until it exits successfully,
# with exponential back off.
#
# $ retry 5 echo Hello
# Hello
#
# $ retry 5 false
# Retry 1/5 "false" exited 1, retrying in 1 seconds...
# Retry 2/5 "false" exited 1, retrying in 2 seconds...
# Retry 3/5 "false" exited 1, retrying in 4 seconds...
# Retry 4/5 "false" exited 1, retrying in 8 seconds...
# Retry 5/5 "false" exited 1, no more retries left.
#
retry() {
local retries=$1
shift
local count=0
until "$@"; do
exit=$?
wait=$((2 ** count))
count=$((count + 1))
if [ $count -lt "$retries" ]; then
log "Retry $count/$retries \"$*\" exited $exit, retrying in $wait seconds..."
sleep $wait
else
log "Retry $count/$retries \"$*\" exited $exit, no more retries left."
return $exit
fi
done
return 0
}