Bash & Shell Scripting Production Runbook: Defensive Syntax, Pipelines & Automation
The ultimate production reference for defensive shell scripting: strict mode (set -euo pipefail), advanced parameter expansions, zero-dependency argument parsing, clean exit signal traps, and reliable pipeline automation.
1. Production Script Boilerplate & Strict Mode
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
# -e: Exit immediately if any command exits with a non-zero status
# -u: Treat unset variables and parameters as fatal errors
# -o pipefail: Pipeline return status is that of the last command to fail
# IFS: Restricts word splitting to newlines and tabs (avoids space bugs)Catches typos, unset environmental variables, and failed intermediate pipeline commands before damage occurs.
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
readonly LOG_FILE="${SCRIPT_DIR}/../logs/app.log"Resolves symlinks and guarantees absolute file path resolution regardless of where the script is called from.
2. Advanced Parameter Expansion (No External Subshells)
# Fallback if unset or null:
PORT="${APP_PORT:-8080}"
# Assign default permanently if unset:
: "${TIMEOUT:=30}"
# Throw custom fatal error if unset:
API_KEY="${PRODUCTION_API_KEY:?Fatal: PRODUCTION_API_KEY must be set in environment}"Handles configuration fallbacks natively without conditional if/else blocks.
FILE="backup_2026-10-23_database.tar.gz"
# Strip shortest/longest prefix:
echo "${FILE#*_}" # 2026-10-23_database.tar.gz
echo "${FILE##*_}" # database.tar.gz
# Strip shortest/longest suffix:
echo "${FILE%.*}" # backup_2026-10-23_database.tar
echo "${FILE%%.*}" # backup_2026-10-23_database
# Global replacement:
echo "${FILE//_/-}" # backup-2026-10-23-database.tar.gzManipulates file names, dates, and delimiters natively at microsecond speed.
| Syntax | Operation Name | Behavior | Copy |
|---|---|---|---|
| ${VAR:-val} | Use default value | Returns val if VAR is unset or empty; does not assign | |
| ${VAR:=val} | Assign default value | Sets VAR=val and returns val if VAR was unset | |
| ${VAR:?err} | Mandatory assertion | Prints err and exits script with 1 if VAR is unset | |
| ${#VAR} | String length | Returns the character length of the variable value | |
| ${VAR%pattern} | Remove suffix (shortest) | Strips shortest match of pattern from end of string | |
| ${VAR##pattern} | Remove prefix (longest) | Strips longest match of pattern from start of string |
3. Defensive Conditionals & Safe Array Iteration
INPUT="v2.0.0"
if [[ "$INPUT" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Valid Semantic Version: $INPUT"
fi
# Combined defensive file check:
if [[ -f "$CONFIG_FILE" && -r "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
fiValidates input formats with native regular expressions without piping to grep.
declare -a TARGET_HOSTS=("node-01.prod" "node-02.prod" "node-03 with spaces.prod")
for host in "${TARGET_HOSTS[@]}"; do
echo "Deploying to: $host"
doneDouble quoting "${TARGET_HOSTS[@]}" guarantees each element remains discrete even if it contains spaces or tabs.
4. Robust Signal Trapping & Atomic Temporary Files
TMP_DIR="$(mktemp -d -t deploy_XXXXXX)"
cleanup() {
local exit_code=$?
echo "Executing cleanup: removing ${TMP_DIR}"
rm -rf "${TMP_DIR}"
exit "$exit_code"
}
trap cleanup EXIT INT TERMThe EXIT pseudo-signal runs on normal completion, syntax errors, and fatal terminations alike.
exec 200>/var/lock/my_cron_task.lock
flock -n 200 || { echo "Task is already running. Exiting." >&2; exit 1; }Prevents overlapping executions when scheduling heavy scripts in cron.
5. Zero-Dependency CLI Flag Parsing (getopts)
usage() {
echo "Usage: $0 [-e environment] [-p port] [-v]" >&2
exit 1
}
ENV="production"
PORT=8080
VERBOSE=0
while getopts "e:p:vh" opt; do
case "$opt" in
e) ENV="$OPTARG" ;;
p) PORT="$OPTARG" ;;
v) VERBOSE=1 ;;
h|*) usage ;;
esac
done
shift $((OPTIND - 1))
echo "Running in $ENV on port $PORT (Verbose: $VERBOSE)"Standardized POSIX flag parser with arguments (-e staging) and boolean flags (-v).
Related Free Online Tools
Put these techniques into practice immediately with our privacy-first browser utilities:
Schedule automated bash shell scripts in system crontab.
Calculate exact execution permissions (chmod +x / 755) for scripts.
Format and number raw output logs and multi-line batch scripts.