A deploy script is a transaction, or it is a hazard — cheat sheet
bash, linux-basics
set -euo pipefail # stop on errors, unset variables, failed pipeline stages
[ "$#" -eq 1 ] || { echo "usage: …" >&2; exit 2; } # argument count, usage on stderr
[ -f "$file" ] || { echo "…: no such file" >&2; exit 1; }
if ! cmd; then cleanup; exit 1; fi # a failure that needs its own response
echo "message" >&2 # diagnostics to stderr
"$var" "$dir/$name" "$(cmd)" "$@" # quote every expansion
dir=$(mktemp -d "/path/prefix.XXXXXX") # a new, unique directory (mode 0700)
rm -rf -- "$dir" # -- : no option parsing after this
ln -sfn target link # replace a link, do not follow a link to a directory
ln -sfn target .link.new && mv -Tf .link.new link # atomic switch (same filesystem)
readlink -f link # where a link finally points
trap 'cleanup' EXIT # run cleanup whenever the script exits
bash -x script args # trace each command after expansion
shellcheck script # static analysis: quoting, common traps
VAR=/tmp/sandbox script args; echo "exit=$?" # test against a throwaway root