Bash Public-Release Script Template (Safe Defaults, Logging, Dry-Run, Strict Mode)
bashA reusable Bash template designed for scripts you plan to publish publicly. Includes strict mode, dependency checks, parameter parsing, safe logging, dry-run support, and environment-agnostic placeholders suitable for homelabs and small production systems.
bashshelltemplateopen-sourceportfoliobest practicesloggingsafetyautomation
Script Code
Bashbash
#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# ScriptedOps Public-Release Bash Template
#
# Purpose:
# A safe, reusable Bash template for scripts you intend to publish publicly.
#
# Features:
# - Strict mode (safer scripting)
# - Dependency checks
# - Argument parsing + usage
# - Dry-run mode (no changes)
# - Logging to console and optional file
# - Environment-agnostic placeholders (no internal names)
#
# Security / Privacy:
# - Do not hardcode credentials, tokens, internal hostnames, or domains
# - Do not include real data samples in comments or output examples
# - Use placeholders and document required inputs clearly
#
# License: MIT (recommended)
# -----------------------------------------------------------------------------
set -euo pipefail
IFS=$'\n\t'
# -----------------------------
# Defaults (safe + generic)
# -----------------------------
TARGET=""
LOG_FILE=""
DRY_RUN="false"
VERBOSE="false"
# -----------------------------
# Helpers
# -----------------------------
timestamp() { date +"%Y-%m-%d %H:%M:%S"; }
log() {
# Usage: log LEVEL MESSAGE...
local level="$1"; shift
local msg="$*"
local line
line="$(timestamp) [$level] $msg"
# Console
case "$level" in
ERROR) echo "$line" >&2 ;;
WARN) echo "$line" ;;
DEBUG) if [[ "$VERBOSE" == "true" ]]; then echo "$line"; fi ;;
INFO|*) echo "$line" ;;
esac
# File
if [[ -n "$LOG_FILE" ]]; then
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true
echo "$line" >> "$LOG_FILE"
fi
}
die() {
log ERROR "$*"
exit 1
}
usage() {
cat <<'EOF'
Usage:
script.sh --target PATH [--log FILE] [--dry-run] [--verbose]
Options:
--target PATH Required. The main target path/resource for the script.
--log FILE Optional. Log file path. If omitted, logs to console only.
--dry-run Optional. Preview actions without making changes.
--verbose Optional. Extra debug logging.
-h, --help Show this help text.
Examples:
# Preview actions
./script.sh --target /var/log --dry-run
# Run with logging
./script.sh --target /var/log --log /var/log/scriptedops-template.log
Notes:
- Keep this script environment-agnostic for public release.
- Do not hardcode secrets or internal hostnames.
EOF
}
require_cmd() {
command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1"
}
assert_target_exists() {
[[ -e "$1" ]] || die "Target does not exist: $1"
}
# -----------------------------
# Argument parsing
# -----------------------------
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--target)
TARGET="${2:-}"; shift 2 ;;
--log)
LOG_FILE="${2:-}"; shift 2 ;;
--dry-run)
DRY_RUN="true"; shift ;;
--verbose)
VERBOSE="true"; shift ;;
-h|--help)
usage; exit 0 ;;
*)
die "Unknown argument: $1 (use --help)" ;;
esac
done
[[ -n "$TARGET" ]] || die "--target is required (use --help)"
}
# -----------------------------
# Main logic (replace placeholders)
# -----------------------------
main() {
parse_args "$@"
# Dependencies (adjust per script)
require_cmd find
require_cmd awk
log INFO "=== Start ==="
log INFO "Target=$TARGET DryRun=$DRY_RUN LogFile=${LOG_FILE:-<none>} Verbose=$VERBOSE"
assert_target_exists "$TARGET"
# Example "work items" (replace with your script’s real target discovery)
# Here: list files under TARGET (depth 1) as a demo.
mapfile -t items < <(find "$TARGET" -maxdepth 1 -type f 2>/dev/null || true)
log INFO "Discovered ${#items[@]} item(s) to process."
for item in "${items[@]}"; do
# Describe intended action
log DEBUG "Candidate: $item"
if [[ "$DRY_RUN" == "true" ]]; then
log INFO "DRY RUN: Would process $item"
continue
fi
# === PLACEHOLDER ACTION ===
# Replace with real operation, e.g.:
# rm -f "$item"
# chmod 600 "$item"
# curl -X POST ...
# systemctl restart ...
#
# Wrap risky actions with error handling:
if ! true; then
log WARN "Non-fatal failure processing: $item"
continue
fi
log INFO "Processed: $item"
done
log INFO "=== End ==="
}
# -----------------------------
# Entrypoint
# -----------------------------
main "$@"Get new scripts weekly.
Subscribe to receive fresh PowerShell scripts, automation tips, and IT workflow improvements.
Subscribe to Newsletter