Advanced Bash Scripting for DevOps Automation (With Copy‑Pasteable Examples)

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

Add a tiny logging helper:

log() { echo "[$(date +'%F %T')] $*"; } die() { log "ERROR: $*"; exit 1; }

Enter fullscreen mode

Exit fullscreen mode

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.

​

7. Safer configuration changes

Always pair config edits with backups.

CONFIG="/etc/myapp/config.yaml" BACKUP="/etc/myapp/config.yaml.$(date +'%F-%H%M%S').bak" cp "$CONFIG" "$BACKUP" sed -i 's/feature_x: false/feature_x: true/' "$CONFIG" systemctl restart myapp

Enter fullscreen mode

Exit fullscreen mode

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

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Читайте також