Linux Basic — Automated Backup Script
Automated Backup Script
A real-world backup script that runs daily from cron, keeps the last 7 days, and logs everything.
Full Script
#!/usr/bin/env bash
set -euo pipefail
PATH=/usr/local/bin:/usr/bin:/bin
BACKUP_SRC="/var/www"
BACKUP_DST="/mnt/backups"
RETENTION_DAYS=7
LOGFILE="/var/log/backup.log"
LOCKFILE="/var/run/backup.lock"
log() { echo "$(date '+%F %T') $*" | tee -a "$LOGFILE"; }
die() { log "ERROR: $*"; exit 1; }
# lock
exec 9>"$LOCKFILE"
flock -n 9 || die "backup already running"
trap 'rm -f "$LOCKFILE"' EXIT
log "starting backup"
# create dated backup dir
today=$(date +%F)
target="$BACKUP_DST/$today"
[[ -d "$target" ]] && die "backup for $today already exists"
mkdir -p "$target" || die "failed to create $target"
# rsync with hard-link to yesterday (incremental)
yesterday=$(date -d '1 day ago' +%F 2>/dev/null || date -v -1d +%F)
link_dest_opt=""
if [[ -d "$BACKUP_DST/$yesterday" ]]; then
link_dest_opt="--link-dest=$BACKUP_DST/$yesterday"
fi
log "running rsync"
rsync -a --delete $link_dest_opt "$BACKUP_SRC/" "$target/" \
|| die "rsync failed"
# retention: delete backups older than RETENTION_DAYS
log "cleaning old backups"
find "$BACKUP_DST" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} + \
|| log "WARN: cleanup had issues"
log "backup complete: $target"
du -sh "$target" | tee -a "$LOGFILE"
How It Works
- Lock file prevents overlapping runs
- rsync with
--link-destcreates space-efficient incrementals - find + mtime removes backups older than 7 days
- All output goes to
$LOGFILEfor auditing
Cron Entry
0 2 * * * /opt/scripts/backup.sh
Runs daily at 2 AM.
Testing Before Cron
Always test manually first:
sudo /opt/scripts/backup.sh
tail -20 /var/log/backup.log
Verify the lock, rsync, and retention all work.
Next → Log Rotation & Cleanup