Exit Codes, Locking, and Idempotency
Good automation is safe to retry and easy to reason about when jobs fail.
Script Pattern
rclone-job-wrapper.sh
#!/usr/bin/env bash
set -euo pipefail
lockfile="/var/lock/rclone-backup.lock"
exec 9>"$lockfile"
flock -n 9 || { echo "job already running"; exit 1; }
rclone sync /srv/data remote-prod:backup/data --log-file /var/log/rclone-job.log
rclone check /srv/data remote-prod:backup/data --one-way
Why Locking Matters
| Without lock | With lock |
|---|---|
| Overlapping jobs compete for bandwidth | Single in-flight transfer |
| Hard-to-explain delete behavior | Deterministic run order |
| Race conditions in post-check steps | Clean success/failure lifecycle |
Idempotency Rules
- Use fixed source and destination mappings.
- Keep job flags consistent between runs.
- Log every run with timestamp or unique ID.
- Make cleanup explicit, never implicit.
Mapping
tip
Treat rclone sync like a database migration: controlled, logged, and reviewable.
Common Pitfalls
| Pitfall | Consequence | Prevention |
|---|---|---|
No set -euo pipefail | Partial failure goes unnoticed | Enable strict shell mode |
| No lock file | Concurrent destructive runs | Use flock or equivalent mutex |
| Ignoring exit code in scheduler | False success reporting | Alert on non-zero status |