Automation Scripts
Build practical automation scripts for backups, deployments, and system tasks.
Automation scripts are where shell skills turn into real value. The goal isn’t “write code that works once” — it’s “write code that works repeatedly, safely, and is easy to operate”.
Design Principles (production‑ready)
- •Idempotent: running twice shouldn’t break things
- •Observable: logs to stderr/syslog + clear exit codes
- •Safe defaults: fail fast (
set -euo pipefail), quote variables, validate inputs - •Configurable: flags/env vars instead of hardcoding paths
- •Locking: prevent overlapping runs (common with cron)
Backup Script Example
#!/bin/bash
set -e
BACKUP_DIR="/backup/$(date +%Y%m%d)"
SOURCE="/home/pranav"
mkdir -p "$BACKUP_DIR"
tar -czvf "$BACKUP_DIR/home.tar.gz" "$SOURCE"
echo "Backup completed: $BACKUP_DIR"
set -e
BACKUP_DIR="/backup/$(date +%Y%m%d)"
SOURCE="/home/pranav"
mkdir -p "$BACKUP_DIR"
tar -czvf "$BACKUP_DIR/home.tar.gz" "$SOURCE"
echo "Backup completed: $BACKUP_DIR"
Improved pattern: safer mode + logging + validation
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
log() { echo "[INFO] $*" >&2; }
die() { echo "[ERROR] $*" >&2; exit 1; }
SOURCE="${1:-}"
[ -n "$SOURCE" ] || die "Usage: $0 /path/to/source"
[ -d "$SOURCE" ] || die "Source not found: $SOURCE"
BACKUP_ROOT="/backup"
BACKUP_DIR="$BACKUP_ROOT/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"
log "Backing up $SOURCE to $BACKUP_DIR"
tar -czf "$BACKUP_DIR/archive.tar.gz" -C "$SOURCE" .
log "Done"
set -euo pipefail
IFS=$'\n\t'
log() { echo "[INFO] $*" >&2; }
die() { echo "[ERROR] $*" >&2; exit 1; }
SOURCE="${1:-}"
[ -n "$SOURCE" ] || die "Usage: $0 /path/to/source"
[ -d "$SOURCE" ] || die "Source not found: $SOURCE"
BACKUP_ROOT="/backup"
BACKUP_DIR="$BACKUP_ROOT/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"
log "Backing up $SOURCE to $BACKUP_DIR"
tar -czf "$BACKUP_DIR/archive.tar.gz" -C "$SOURCE" .
log "Done"
Log Rotation Script
#!/bin/bash
LOG_DIR="/var/log/myapp"
MAX_SIZE=10485760 # 10MB
for log in "$LOG_DIR"/*.log; do
size=$(stat -f%z "$log" 2>/dev/null || stat -c%s "$log")
if [ "$size" -gt "$MAX_SIZE" ]; then
mv "$log" "$log.$(date +%Y%m%d)"
gzip "$log.$(date +%Y%m%d)"
fi
done
LOG_DIR="/var/log/myapp"
MAX_SIZE=10485760 # 10MB
for log in "$LOG_DIR"/*.log; do
size=$(stat -f%z "$log" 2>/dev/null || stat -c%s "$log")
if [ "$size" -gt "$MAX_SIZE" ]; then
mv "$log" "$log.$(date +%Y%m%d)"
gzip "$log.$(date +%Y%m%d)"
fi
done
Locking: prevent overlapping runs
If cron runs your script every 5 minutes but one run takes 8 minutes, you’ll get overlaps.
Use a lock file or flock.
# Example using flock (preferred when available)
flock -n /var/lock/myjob.lock -c "/usr/local/bin/myjob.sh"
flock -n /var/lock/myjob.lock -c "/usr/local/bin/myjob.sh"
Scheduling + Observability
Automation should be “boring”: scheduled, logged, and alerting on failures.
- •cron: simplest scheduler; redirect logs to a file
- •systemd timers: better logs + dependencies + status
✅ Practice (30 minutes)
- Write a script that rotates logs and adds a timestamp suffix, then compresses older logs.
- Add argument validation and a
--dry-runmode (print actions instead of executing). - Wrap it with
flockso overlapping runs can’t happen.