rsync Large-Dataset Migration & Verification Prompt
Plan, tune, and verify a large rsync data migration (terabytes / millions of files) — pick the right flags, avoid resync churn, throttle load, and prove the copy is byte-correct before cutover.
- Target user
- Senior Linux admins and SREs migrating bulk data between hosts, arrays, or filesystems
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT
The prompt
You are a senior Linux storage engineer who has migrated multi-terabyte datasets and dense small-file trees (mail spools, image stores, home directories) between hosts, SANs, and filesystems with rsync. You know which flags preserve metadata, which cause needless re-copies, and how to verify correctness without trusting the transfer log. I will provide: - Source and destination paths, and whether they are local, over SSH, or via rsync daemon (`rsync://`) - Dataset shape: total size, approximate file count, and average file size (many tiny files behaves very differently from a few huge ones) - Source and destination filesystems (ext4, xfs, zfs, btrfs, nfs) and whether ACLs, xattrs, or hardlinks are in use - The constraint that matters most: minimize downtime, minimize source I/O load, or fastest wall-clock time - Link between hosts: LAN 10G, WAN, or same-host different disk - Whether this is a one-shot copy or an incremental "pre-seed then final sync at cutover" migration Your job: 1. **Choose the flag set deliberately** and explain each choice: - `-a` (`-rlptgoD`) is the baseline archive mode, but call out what it does NOT cover: `-A` (ACLs), `-X` (xattrs — needed for SELinux labels), `-H` (hardlinks — critical for Maildir/backups, expensive in RAM), `--numeric-ids` (when UID/GID maps differ between hosts). - When to DROP flags: `-o`/`-g` are pointless if the target UIDs don't exist; `--times` mismatches cause full re-copies if clocks or filesystem timestamp granularity differ. 2. **Avoid the classic "it re-copies everything" traps**: - Trailing-slash semantics: `src/` vs `src` changes whether you nest a directory. State the exact resulting layout. - Checksum vs quick-check: default is size+mtime; `-c` forces full checksum (slow, only when mtimes are untrustworthy). - `--delete` only on the FINAL sync, never on the seed pass, and always dry-run first. 3. **Tune for the dataset shape**: - Millions of small files → the bottleneck is metadata/IOPS and rsync's in-memory file list. Recommend `--info=progress2`, splitting the tree across parallel rsync processes (per top-level dir or via `xargs`/`parallel`), and warn about `-H` memory cost. - Few huge files → the bottleneck is throughput; consider `--partial --append-verify` for resumability and compression only on WAN (`-z` wastes CPU on LAN / already-compressed data). 4. **Control blast radius on production source**: - `--bwlimit` to cap bandwidth, `ionice -c2 -n7` / `nice` to deprioritize, and running during low-traffic windows. 5. **Design the cutover** as: (a) initial seed while source is live, (b) one or more incremental catch-up syncs, (c) brief source freeze / read-only, (d) final `--delete` sync, (e) verify, (f) switch. 6. **Verification that actually proves correctness** — never trust "rsync exited 0" alone: - A final `-anc --delete` dry-run should report zero changes. - Independent checks: file counts (`find | wc -l`), total bytes (`du -sb`), and a checksum manifest (`find -type f -print0 | sort -z | xargs -0 sha256sum`) compared on both sides. 7. **Restartability**: recommend `--partial-dir`, logging (`--log-file`), and how to safely re-run after an interruption without corruption. Mark DESTRUCTIVE: any command using `--delete`, `--delete-excluded`, or a wrong trailing slash that could wipe or duplicate the destination; running `-c` full-checksum against a live spinning-disk source during business hours; `-H` on a huge tree without checking available RAM. Give me: (1) the exact recommended rsync command(s) for the seed and final passes, (2) the verification commands, (3) a short cutover runbook, and (4) the top 3 risks specific to my dataset shape. --- Source → Destination: [e.g. /srv/data/ on host-a → /mnt/newarray/data/ on host-b over SSH] Dataset shape: [total size, file count, avg file size] Filesystems (src/dst) + ACL/xattr/hardlink usage: [...] Primary constraint: [min downtime | min source load | fastest wall-clock] Link: [LAN 10G | WAN | same-host] Migration style: [one-shot | seed + final cutover]
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
Most rsync failures in migrations are not crashes — they are silent correctness problems: data nested one directory too deep by a stray slash, ownership landing on the wrong UIDs, a “quick” resync that re-copies terabytes because timestamps didn’t match, or a decommissioned source after a copy that was never actually verified. This prompt forces the model to justify every flag against the specific dataset shape and to design an independent verification step rather than trusting rsync’s own exit status.
How to use it
- Describe the dataset shape honestly — “20 TB in 400 files” and “300 GB in 60 million files” need completely different strategies (throughput vs metadata/IOPS).
- State the one constraint that dominates — minimizing downtime leads to a seed-plus-cutover design; minimizing source load leads to
--bwlimitandionice. - Run the seed pass early and often so the final cutover sync only has to move the delta.
- Never skip the verification manifest, especially before you delete or reformat the source.
Useful commands
# Dry-run a seed pass and see what would move (no changes made)
rsync -aHAX --numeric-ids -n --info=stats2 /srv/data/ host-b:/mnt/newarray/data/
# Seed pass, resumable, throttled, logged
ionice -c2 -n7 nice -n10 rsync -aHAX --numeric-ids \
--partial --partial-dir=.rsync-partial --bwlimit=200M \
--info=progress2 --log-file=/var/log/rsync-seed.log \
/srv/data/ host-b:/mnt/newarray/data/
# Final cutover sync (source frozen / read-only), mirror deletions
rsync -aHAX --numeric-ids --delete --partial \
--log-file=/var/log/rsync-final.log \
/srv/data/ host-b:/mnt/newarray/data/
# Prove convergence: this must report zero changes
rsync -ancHAX --delete /srv/data/ host-b:/mnt/newarray/data/
# Independent verification (run on both hosts, compare)
find /path -xdev -type f | wc -l # file count
du -sb --exclude=lost+found /path # total bytes
find /path -xdev -type f -print0 | sort -z | xargs -0 sha256sum > /tmp/manifest.sha256
Parallelizing dense small-file trees
When rsync is metadata-bound (millions of tiny files), a single stream underuses the link. Split by top-level directory:
# Copy each top-level dir concurrently (4 at a time)
cd /srv/data
ls -1 | xargs -P4 -I{} rsync -aHAX --numeric-ids {}/ host-b:/mnt/newarray/data/{}/
Each process keeps its own file list, so memory and comparison work is bounded per subtree instead of one giant list.
Common findings this catches
- Trailing-slash mistake duplicating or nesting the tree — caught by reading the dry-run’s destination paths.
- Full re-copy every run because source/destination timestamp granularity differs (e.g. FAT/NFS) — fixed with
--modify-windowor accepted with size-only checks. -HOOM risk on backup/Maildir trees flagged before it kills the job mid-migration.- Missing
-Xdropping SELinux labels, leaving the destination unbootable or servicesavc: deniedafter cutover. - “Verified” by exit code only — replaced with a real convergence dry-run plus checksum manifest.
When to escalate
- Datasets where the change rate exceeds the sync rate (source mutates faster than you can catch up) — need a filesystem-level snapshot/replication approach (
zfs send,btrfs send, LVM snapshot) instead of rsync. - Cross-filesystem feature gaps (source has xattrs/ACLs/reflinks the destination filesystem cannot represent) — decide what is acceptable to lose before cutover.
- Sustained transfers that must survive reboots and span days — wrap in a systemd service or
tmux/screenwith resumable--partial-dirand monitored logs.
Related prompts
-
Linux bcache SSD Caching Setup Prompt
Design a bcache SSD-in-front-of-HDD caching tier with the right cache mode, write policy, and sequential-bypass tuning, and plan the attach/detach and failure behavior so a cache device loss never means data loss.
-
Linux fio Storage Benchmark Design Prompt
Design fio job files that model your real workload (block size, queue depth, read/write mix, fsync policy) and interpret IOPS, throughput, and latency percentiles without fooling yourself with cache or preconditioning artifacts.
-
Linux nvme-cli SSD Health Management Prompt
Interpret nvme-cli smart-log, error-log, and self-test output to decide whether an NVMe drive is healthy, wearing out, thermally throttling, or in pre-failure, and plan namespace, firmware, and format actions safely.
-
ddrescue Disk Imaging and Recovery Runbook Prompt
Plan a safe GNU ddrescue recovery of a failing disk: choose the right pass strategy, use a mapfile for resumable multi-pass runs, and decide when to stop imaging and switch to filesystem repair.
More Linux Admins prompts & error guides
Browse every Linux Admins prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.