2026-06-10
Every greybeard has been here: a drive is failing, SMART is screaming, and someone wants the data. You reach for dd, hit the first bad sector, and watch the kernel retry for ten minutes while the head bangs itself to death. Then the command dies and you've got nothing — no image, no idea which blocks made it, no way to resume.
GNU ddrescue (not the unrelated dd_rescue, which is a different tool from a different author) was written by Antonio Diaz Diaz in 2004 for exactly this problem. It is the right tool, and almost nobody in your office knows it exists until they need it.
The trick is the mapfile (older docs call it a logfile). ddrescue records exactly which sectors are good, bad, untried, or non-trimmed, persists that map after every block, and uses it to resume. So you do a fast first pass grabbing all the easy data, then come back for the failing sectors after the good data is already safe on another disk.
# Pass 1: skip aggressively past errors, no retries.
# Get the easy 95% before the drive dies completely.
ddrescue -f -n -b4096 /dev/sdb /mnt/safe/image.img /mnt/safe/sdb.map
# Pass 2: now retry the holes the map says are bad.
# Reverse direction often helps when the head is stuck.
ddrescue -f -d -r3 -R /dev/sdb /mnt/safe/image.img /mnt/safe/sdb.map
Flags worth knowing:
-n / --no-scrape: skip the slow read-every-byte-of-a-bad-block phase on the first pass.-d: open with O_DIRECT so you bypass the kernel page cache (no fake-good reads from RAM).-r3: retry bad areas three times before giving up.-R: reverse direction. Spinning drives sometimes read backwards better.-b4096: physical sector size. Matters for 4K-native drives.-i / -s: input position and size. Carve out just one partition.--domain-mapfile: limit work to a previous run's good or bad areas.Resuming is automatic — point at the same mapfile and ddrescue picks up where it stopped. You can yank the drive, refrigerate it overnight (yes, really, this is a documented technique for stiction-prone heads), and continue tomorrow. The mapfile is plain text:
$ head -5 sdb.map
# Mapfile. Created by GNU ddrescue version 1.27
# current_pos current_status current_pass
0x1A3F4000 ? 2
# pos size status
0x00000000 0x1A3F4000 +
0x1A3F4000 0x00001000 *
Status codes: + finished, ? untried, * non-trimmed, / non-scraped, - bad. You can hand-edit it to force a retry of a region, or feed it to ddrescueview for a graphical heatmap of the drive.
One more trick: rescuing from an already-partial image works. If your colleague started with naive dd conv=noerror,sync and produced a partial file full of zero-filled holes, ddrescue can read the original drive and only fill the gaps:
ddrescue --generate-mode /dev/sdb partial.img generated.map
ddrescue -d -r3 /dev/sdb partial.img generated.map
The mainstream alternative — dd conv=noerror,sync — retries forever on bad sectors, has no resume, no map, and silently substitutes zeroes. It's the wrong tool. ddrescue treats the failing drive as a resource to harvest carefully, not a punching bag.
dd wastes its remaining life thrashing on bad sectors; ddrescue's mapfile lets you grab the good data fast, then negotiate with the bad sectors afterward — with full resume, reverse reads, and a plain-text record of exactly what survived.
