I have written about ddrescue in an article before, but just mentioned it without explaining how to use it.

As I had to use it again this weekend, here is how things go:

Install ports

1. Go to:https://www.macports.org/install.php and download your ports version of choice.
2. reboot
3. sudo port -v selfupdate

Install ddrescue

sudo port install ddrescue

This can even go without xcode:

Warning: xcodebuild exists but failed to execute
Warning: Xcode does not appear to be installed; most ports will likely fail to build.

Test installation:

ddrescue --help
GNU ddrescue - Data recovery tool.
Copies data from one file or block device to another,
trying to rescue the good parts first in case of read errors.

Usage: ddrescue [options] infile outfile [mapfile]

Always use a mapfile unless you know you won't need it. Without a
mapfile, ddrescue can't resume a rescue, only reinitiate it.
NOTE: In versions of ddrescue prior to 1.20 the mapfile was called
'logfile'. The format is the same; only the name has changed.

If you reboot, check the device names before restarting ddrescue.
Do not use options '-F' or '-G' without reading the manual first.

  -h, --help                     display this help and exit
  -V, --version                  output version information and exit
  -a, --min-read-rate=    minimum read rate of good areas in bytes/s
  -A, --try-again                mark non-trimmed, non-scraped as non-tried
  -b, --sector-size=      sector size of input device [default 512]
  -B, --binary-prefixes          show binary multipliers in numbers [SI]
  -c, --cluster-size=   sectors to copy at a time [128]
  -C, --complete-only            do not read new data beyond mapfile limits
  -d, --idirect                  use direct disc access for input file
  -D, --odirect                  use direct disc access for output file
  -e, --max-errors=[+]        maximum number of [new] error areas allowed
  -E, --max-error-rate=   maximum allowed rate of read errors per second
  -f, --force                    overwrite output device or partition
  -F, --fill-mode=        fill blocks of given types with data (?*/-+l)
  -G, --generate-mode            generate approximate mapfile from partial copy
  -H, --test-mode=         set map of good/bad blocks from given mapfile
  -i, --input-position=   starting position of domain in input file [0]
  -I, --verify-input-size        verify input file size with size in mapfile
  -J, --verify-on-error          reread latest good sector after every error
  -K, --skip-size=[,]  initial size to skip on read error [64 KiB]
  -L, --loose-domain             accept an incomplete domain mapfile
  -m, --domain-mapfile=    restrict domain to finished blocks in file
  -M, --retrim                   mark all failed blocks as non-trimmed
  -n, --no-scrape                skip the scraping phase
  -N, --no-trim                  skip the trimming phase
  -o, --output-position=  starting position in output file [ipos]
  -O, --reopen-on-error          reopen input file after every read error
  -p, --preallocate              preallocate space on disc for output file
  -P, --data-preview[=]   show some lines of the latest data read [3]
  -q, --quiet                    suppress all messages
  -r, --retry-passes=         exit after  retry passes (-1=infinity) [0]
  -R, --reverse                  reverse the direction of all passes
  -s, --size=             maximum size of input data to be copied
  -S, --sparse                   use sparse writes for output file
  -t, --truncate                 truncate output file to zero size
  -T, --timeout=       maximum time since last successful read
  -u, --unidirectional           run all passes in the same direction
  -v, --verbose                  be verbose (a 2nd -v gives more)
  -w, --ignore-write-errors      make fill mode ignore write errors
  -x, --extend-outfile=   extend outfile size to be at least this long
  -X, --exit-on-error            exit after the first read error
  -y, --synchronous              use synchronous writes for output file
  -1, --log-rates=         log rates and error sizes in file
  -2, --log-reads=         log all read operations in file
      --ask                      ask for confirmation before starting the copy
      --cpass=[,]          select what copying pass(es) to run
      --max-read-rate=    maximum read rate in bytes/s
      --pause=         time to wait between passes [0]
Numbers may be in decimal, hexadecimal or octal, and may be followed by a
multiplier: s = sectors, k = 1000, Ki = 1024, M = 10^6, Mi = 2^20, etc...
Time intervals have the format 1[.5][smhd] or 1/2[smhd].

Exit status: 0 for a normal exit, 1 for environmental problems (file
not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or
invalid input file, 3 for an internal consistency error (eg, bug) which
caused ddrescue to panic.

Report bugs to bug-ddrescue@gnu.org
Ddrescue home page: http://www.gnu.org/software/ddrescue/ddrescue.html
General help using GNU software: http://www.gnu.org/gethelp

Find the right disk

diskutil list

Start ddrescue

sudo ddrescue -v /dev/disk3s2 /Volumes/backup/failing_drive_backup.dmg failing_drive_backup.log
GNU ddrescue 1.20
About to copy an unknown number of Bytes from /dev/disk3s2 to /Volumes/backup/failing_drive_backup.dmg.
    Starting positions: infile = 0 B,  outfile = 0 B
    Copy block size: 128 sectors       Initial skip size: 128 sectors
Sector size: 512 Bytes

Press Ctrl-C to interrupt
rescued:     7621 MB,   errsize:         0 B,    current rate:  10878 kB/s
   ipos:     7621 MB,    errors:         0,      average rate:  10484 kB/s
   opos:     7621 MB,  run time:      12m 7s,  remaining time:         n/a
time since last successful read:          0s


Found an good recommendation from Christian Schwang:

– instead of /dev/disk{x} you may use /dev/rdisk{x} – This will give a massive performance boost (in my testing transfer rate went from 30 MB to 130 MB). For detailed reason you may want to look at: http://lists.apple.com/archives/filesystem-dev/2012/Feb/msg00015.html

Result with the same drive as above:

sudo ddrescue -v /dev/rdisk3s2 /Volumes/backup/failing_drive_backup2.dmg failing_drive_backup2.log
GNU ddrescue 1.20
About to copy an unknown number of Bytes from /dev/rdisk3s2 to /Volumes/backup/failing_drive_backup2.dmg.
    Starting positions: infile = 0 B,  outfile = 0 B
    Copy block size: 128 sectors       Initial skip size: 128 sectors
Sector size: 512 Bytes

Press Ctrl-C to interrupt
rescued:     5215 MB,   errsize:         0 B,    current rate:  34209 kB/s
   ipos:     5215 MB,    errors:         0,      average rate:  33649 kB/s
   opos:     5215 MB,  run time:      2m 35s,  remaining time:         n/a
time since last successful read:          0s

Known issues

drescue: Can't open input file: Resource busy

Solution: Open the DiskUtility.app, and on your to-be-recued-drive, unmount any of it’s partitions.
Warning: Do not eject the USB hard drive.

more infos


Recovering Photos From Bad Storage Cards (with ddrescue)

Today, Jonathan Zdziarski wrote a Blog post about recovery of Photos on a corrupt SD card. In total, the article is very good, but I would prefer to use ddrescue instead of dd only.

Had good expieriences with ddrescue in the past while recover data from SD cards and HDDs as well.

Hope this helps