Advanced Bash Scripting for DevOps Automation (With Copy‑Pasteable Examples)
Jenkins
Source: Dev.to | Jan 09, 2026 (UTC)
Bash is still the glue that holds a lot of DevOps workflows together. Whether you’re deploying services, wiring health checks into CI, or cleaning up logs on a forgotten VM, a few solid scripting patterns go a very long way. In this post, you’ll find copy‑pasteable Bash snippets for:
Safer script defaults
Parameterized deployments
Health checks and rollbacks
Log rotation and cleanup
Simple CPU/memory watchdogs
Everything is written with day‑to‑day DevOps work in mind—not contrived toy examples.
1. Bash foundations that prevent outages
Even experienced engineers skip basics that later cause flaky scripts and silent failures.
#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t'
Enter fullscreen mode
Exit fullscreen mode
set -e – exit on the first error instead of continuing in a bad state
set -u – fail if a variable is undefined
set -o pipefail – make pipelines fail if any command fails
This alone makes every script more observable and safer to reuse across environments.
2. Parameters, flags, and environment‑aware scripts
Hard‑coding values is fine for demos, but production scripts must be configurable. Use arguments with sensible defaults:
#!/usr/bin/env bash set -euo pipefail ENVIRONMENT="${1:-staging}" log() { echo "[$(date +'%F %T')] [$ENVIRONMENT] $*"; } log "Deploying to $ENVIRONMENT"
Enter fullscreen mode
Exit fullscreen mode
For more control, turn your script into a tiny CLI:
while getopts "e:v:h" opt; do case "$opt" in e) ENVIRONMENT="$OPTARG" ;; v) VERSION="$OPTARG" ;; h) echo "Usage: deploy.sh -e <env> -v <version>"; exit 0 ;; *) exit 1 ;; esac done
Enter fullscreen mode
Exit fullscreen mode
Now teammates and CI pipelines can call the same script with explicit flags.
3. A realistic deployment script pattern
Here’s a trimmed‑down deployment flow you can adapt for your services.
#!/usr/bin/env bash set -euo pipefail ENVIRONMENT="${1:-staging}" APP_DIR="/srv/myapp" REPO_URL="[email protected]:org/myapp.git" log() { echo "[$(date +'%F %T')] [$ENVIRONMENT] $*"; } deploy() { log "Updating code..." if [[ ! -d "$APP_DIR/.git" ]]; then git clone "$REPO_URL" "$APP_DIR" fi cd "$APP_DIR" git fetch --all git checkout main git pull --ff-only log "Installing dependencies..." npm ci log "Running tests..." npm test log "Building..." npm run build log "Restarting service..." sudo systemctl restart myapp log "Deployment complete." } deploy
Enter fullscreen mode
Exit fullscreen mode
This pattern is idempotent, easy to wire into CI/CD, and uses systemd for reliable service restarts.
4. Health checks and rollbacks in one script
Automation without safety is just a faster way to ship broken code. Add health checks:
health_check() { local url="${1:-http://localhost/health}" if curl -fsS "$url" > /dev/null; then log "Health check passed for $url" else die "Health check FAILED for $url" fi }
Enter fullscreen mode
Exit fullscreen mode
Then define a simple rollback:
previous_version() { git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "" } rollback() { local prev prev="$(previous_version)" [[ -z "$prev" ]] && die "No previous version found for rollback" log "Rolling back to $prev" git checkout "$prev" npm run build sudo systemctl restart myapp }
Enter fullscreen mode
Exit fullscreen mode
Wire it together:
deploy if ! health_check "https://myapp.example.com/health"; then log "Health check failed; rolling back" rollback fi
Enter fullscreen mode
Exit fullscreen mode
You now have a single script that deploys, validates, and self‑heals.
5. Log rotation and cleanup that actually runs
Not every environment needs a full‑blown logging stack; Bash plus cron still works well. Compress older logs:
#!/usr/bin/env bash set -euo pipefail LOG_DIR="/var/log/myapp" DAYS_TO_KEEP=7 find "$LOG_DIR" -type f -name "*.log" -mtime +$DAYS_TO_KEEP -print0 \ | while IFS= read -r -d '' file; do gzip "$file" done
Enter fullscreen mode
Exit fullscreen mode
Remove stale archives:
find "$LOG_DIR" -type f -name "*.gz" -mtime +30 -delete
Schedule it:
30 1 * * * /usr/local/bin/log_cleanup.sh
That’s often enough to keep disks from filling up silently.
6. Lightweight monitoring and alert hooks
You can wrap traditional Linux tools in Bash and push alerts to Slack, email, or a webhook endpoint.
#!/usr/bin/env bash set -euo pipefail CPU_THRESHOLD=80 MEM_THRESHOLD=80 cpu_usage() { mpstat 1 1 | awk '/Average/ && $12 ~ /[0-9.]+/ {print 100-$12}' } mem_usage() { free | awk '/Mem:/ {printf("%.0f", $3/$2 * 100)}' } CPU=$(cpu_usage) MEM=$(mem_usage) if (( CPU > CPU_THRESHOLD || MEM > MEM_THRESHOLD )); then echo "High usage detected: CPU=${CPU}% MEM=${MEM}%" # TODO: send to Slack / email / webhook here fi
Enter fullscreen mode
Exit fullscreen mode
This is a great complement to Prometheus, Grafana, or hosted solutions.
This pattern makes it trivial to revert a bad change during an incident.
If you adapt any of these snippets into your own tooling, drop a comment with your variations—other engineers will benefit from seeing real‑world tweaks. Also, tell which part you’d like to see expanded: deployments, monitoring, or incident tooling.
For further actions, you may consider blocking this person and/or reporting abuse
Залишити відповідь