Recovering data, even after a SMART failure — using GNU ddrescue in macOS

Alex Santos
15 min readFeb 10, 2017

--

What is ddrescue?

GNU ddrescue is a data recovery tool. It copies data from one file or block device (hard disk, cdrom, etc) to another, trying to rescue the good parts first in case of read errors.

The basic operation of ddrescue is fully automatic. That is, you don’t have to wait for an error, stop the program, restart it from a new position, etc.

Ddrescue manages efficiently the status of the rescue in progress and tries to rescue the good parts first, scheduling reads inside bad (or slow) areas for later. This maximizes the amount of data that can be finally recovered from a failing drive.

The sole intention of this article is to help you recover data from a hard drive that is failing or has failed the SMART (Self-Monitoring, Analysis and Reporting Technology) status making the hard drive unreliable or even unmountable. If you have a backup of the drive you don’t need to read on. This process will not fix your hard drive, it will only help you recover as much data as allowed onto another hard drive.

For the most part, the focus is on a recovery method that is triggered through a simple Terminal command and is a Mac centric article but the tool of choice, ddrescue, is available on multiple platforms. I will go through the process as simply as I can.

I have an iMac 27-inch, Mid 2011, i7 3.4GHz computer with 32GB of RAM, two internal hard drives, an SSD for the OS and a rotational drive for my user account. The original 1TB hard drive that shipped with this iMac died about 1 year ago so a Hitachi 2TB rotational drive and an OWC SSD was added on without sacrificing the optical drive.

The Hitachi drive reports a SMART failure after a little less than a year in operation. The symptom was singular, aggressive spinning beachball of death, also known as BBOD that appeared suddenty and persisted for about 15 minutes until I was finally able to restart. After restart, I ran disk utility from the recovery partition and there it was tatooed in the Disk Utility window, SMART status, failing.

The spinning beachball symptom was quickly isolated to an internal hard drive failing SMART. The next step was recovering data that had not been picked up by Time Machine.

The spinning beach ball of death (BBOD) took domination over the entire machine for a very long time. This usually indicates some irregularity with a hard drive.

How I present information

Please use this as a reference of sorts for ddrescue. Examples and screenshots are included at times. Hopefully the knowledge presented will help you recover data off a drive sitting on a shelf or in the future.

Backup Backup Backup

The takeaway is clear, backup! You should always have a proper backup policy in place. I personally use an external drive as a Time Machine backup and it has saved my butt more than once. As long as you backup your data you can avoid all of this, it does’t matter which technology you use, just please backup.

Software requirements

Homebrew
Cakebrew (GUI front end for Homebrew) — nice to have but not neceesary for the task

ddrescue
ddrescue-GUI (GUI front end for ddrescue)

The GUI versions for each require the command line versions be installed first. Once installed you can use the GUIs on their own and forget about the Terminal. I will be focusing on the command line versions only.

Install Homebrew

Launch the Terminal from the /Applications/Utilities folder or from Spotlight. Copy the line below and paste it at the Terminal prompt, or copy and paste the same from Homebrew’s home at brew.sh.

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrew requires Apple’s Xcode Command Line Tools. Brew will instruct you on how to install these if it is not already installed on your system. It should ask you to type the following command.

xcode-select --install

Now we need to be sure Homebrew is happy.

brew doctor

If the results of brew doctor are, “Your system is ready to brew.” we can continue …

Install ddrescue

To install ddrescue enter the following

brew install ddrescue

Some quick tips

Tip: If you want to visit a package’s home page from the Terminal you can. For example, if you would like to quickly open ddrescue’s home page simply enter;

brew home ddrescue

Tip: If you want to search for a package you can enter a partial name like this;

brew search rescue

As I write this the result are; the checkmark below means I have it installed.

ddrescue ✔Caskroom/cask/data-rescue                           Caskroom/cask/phonerescue                           Caskroom/cask/rescuetime

Tip: If you enter the following, you will get a list of what packages are installed and managed by brew, as in brew will update those with the proper commands.

brew list

More useful Software

Install Homebrew Cask

Home-brew Cask extends Homebrew so that it can reach out, or tap into the Cask repository. Requires Homebrew as a prerequisite install but it installs with 1 line in your shell.

brew tap caskroom/cask

Install Disk Arbitrator

This app is not a command line tool, instead it is an iconized app that installs into /Applications. Use the line below to install it.
- Requires tapping into Cask via Homebrew first.

brew install Caskroom/cask/disk-arbitrator
Once launched, Disk Aribtrator is accessed as a menu item.

Never try to rescue a r/w mounted partition. The resulting copy may be useless. It is best that the device or partition to be rescued is not mounted at all, not even read-only.

Hardware requirements

  1. The affected drive (the source drive), meaning the drive we need to recovery data from.
  2. A second drive (the destination drive) with the same or greater storage space than the affected drive. This is required because ddrescue creates a disk image of the entire affected drive and saves it to the destination drive.

These requirements should tell you something about how important it is to backup as regularly as possible. For one, ddrescue can take a long time to recover a drive. In my particular case, ddrescue has been running dutifully for about a week and a half on a 2TB drive and so far 1.34TB has been recovered. At this pace, if sustainable, it should complete in a few more days.

This raises another point, think carefully before purchasing those colossal 6, 8, 10 and now 12TB single drives. With 16TB single drives on the horizon, either way you will need a second drive with at least the same amount of storage space for backup alone so please plan your storage needs accordingly.

Using ddrescue safely (from the manual)

ddrescue is like any other power tool. You need to understand what it does, and you need to understand some things about the machines it does those things to, in order to use it safely.

1

  • Never try to rescue a r/w mounted partition. The resulting copy may be useless. It is best that the device or partition to be rescued is not mounted at all, not even read-only.

Install Disk Arbitrator and block mounts, then eject the affected drive using the Finder.

2

  • Never try to repair a file system on a drive with I/O errors; you will probably lose even more data.

If your device has I/O errors and the data is critical DO NOT use ddrescue, instead seek data recovery services from a company like drivesavers.com. They do operate globally.

To check for Input/Output errors, launch the Console from /Applications/Utilities. Select All Messages from the left-hand side panel followed by a search for “I/O error”. The drive I am recovering from does in fact have I/O errors but because the data is recoverable from an FTP server I chose to continue with ddrescue.

If you can’t get to the console for some reason type the following in Terminal. It will keep updating as required.

tail -f /var/log/system.log

3

  • If you use a device or a partition as destination, any data stored there will be overwritten.
  • Some systems may change device names on reboot (eg. udev enabled systems). If you reboot, check the device names before restarting ddrescue.

From the Terminal enter the following command.

diskutil list

From the resulting list use the Identifier column to determine the device that you need to recover from. As noted, a restart may result in the disk identifier changing.

Additional Information
The disk identifier string variously identifies a device unit, a session upon that device, or a partition (slice) upon that session. It may take the form of diskU, diskUsS, diskUsQ, or diskUsQsS, where U, S, and Q are positive decimal integers (possibly multi-digit), and where:

In my case disk0 (disk zero) is the affected drive, we have slice 1 and 2, disk0s1 and disk0s2 respectively but I am recovering the entire device unit, disk0. What is important here is that the Identifier may change after a reboot so run diskutil list on reboot.

+ U is the device unit. It may refer to hardware (e.g. a hard drive, optical drive, or memory card) or a “drive” constructed by software (e.g. an AppleRAID set or a disk image).

+ Q is the session and is only included for optical media; it refers to the number of times recording has taken place on the currently-inserted medium (disc).

+ S is the slice; it refers to a partition. Upon this partition, the raw data that underlies a user-visible file system is usually present, but it may also contain specialized data for certain 3rd-party database programs, or data required for the system software (e.g. EFI or booter partitions, or APM partition map data).

4

  • If you interrupt the rescue and then reboot, any partially copied partitions should be hidden before allowing them to be touched by any operating system that tries to mount and “fix” the partitions it sees.

Eject the affected hard drive using the Finder then launch Disk Arbitrator to prevent mounting. Consider whether your system has an app(s) installed that may intercept a drive as per the last bullet point. If so, refer to the developer’s site for the required steps to turn off such finctionality.

ddrescue usage

The format for running ddrescue is:

ddrescue [OPTIONS] INFILE OUTFILE [MAPFILE]

INFILE and OUTFILE may be files, devices or partitions. MAPFILE is a regular text file and must be placed in an existing directory. According to the ddrescue manual,

… if the MAPFILE does not exist, ddrescue will create it. Without a mapfile, ddrescue can’t resume a rescue. If ddrescue is interrupted or otherwise, it can only reinitiate the recovery.

Let’s look at the command format as mentioned above but in detail so that we can use this tool going forward.

Again, usage looks like this ddrescue [OPTIONS] INFILE OUTFIELD [MAPFILE]

Formatting ddrescue explained

⚠️ Please DO NOT copy and paste the example below into your terminal window because your drives may be completely different.

Below is ddrescue properly formatted for use. An explanation follows.

sudo ddrescue -v /dev/disk0 /dev/disk6/image_bad_drive.dmg /dev/disk6/mapfile.txt

sudo necessary for executing ddrescue. After hitting enter you are required to type your admin password to be granted permission to execute ddrescue. The password prompt does not feedback as you type.

ddrescue is the command

-v (verbose mode) this option instructs ddrescue to display what it is doing on screen. Further -v’s (up to 4) increase the verbosity level.

/dev/disk0 this is the drive I want to recover from as per diskutil list

/dev/disk6/image_bad_drive.dmg /dev/disk6 is the destination drive and all of disk0 (disk zero) will get copied into a file called ‘image_bad_drive.dmg’
- The dmg file is created by virtue of the command, you don’t need to create it first.

/dev/disk6/mapfile.txt This creates a mapfile.txt on disk6 for me. This file is very important because if you stop ddrescue it can continue the next time it is invoked.

More ddrescue options

[OPTIONS], there are many. For example if you want a list of all the options type ddrescue -help into a Terminal window. Incidentally -help is an option itself.

ddrescue -help

You can read up more on the various [OPTIONS] in section 5 of the ddrescue manual, titled “Invoking ddrescue”. Alternatively, you can enter either of the following commands from the Terminal.

man ddrescueORinfo ddrescue

info ddrescue will open the GNU ddrescue manual, also served here, https://www.gnu.org/software/ddrescue/manual/ddrescue_manual.html#Invoking-ddrescue.

From the info window in the Terminal you can navigate using N key for Next Page and the P key for the Previous Page.

Left: GNU ddrescue Manual on the web | Right: Info page for GNU ddrescue Manual. They both present identical information, only the presentation differs.

Conclusion and remarks

You should now have enough information to start. If you are at all enthusiastic you will learn. I am constantly referring to the ddrescue manual for more information.

man ddrescueORinfo ddrescue

My own data recovery story

The drive I am recovering from does indeed have i/o errors. I haven’t learned if there is yet a solution although I am looking into it. At this rate this is an educational experience for me.

The drive, aside from having confirmed i/o errors, which of course means I should not run ddrescue but the data on it can actually get reproduced via an FTP mirror but here is what the drive does.

As of this writing ddrescue will sit there and wait for the drive for 10 minutes at a time while displaying a current read rate of 0 B/s, that zero Bytes a second, it couldn’t be slower. The drive is rather rapidly deteriorating. During those 10 minute periods of silence I can here the drive clunk, clunk, clunk, it’s a very deliberately timed rhythm that gives the sense the drive is attempting to read but can’t continue. Suddenly it will begin to read at over 50MB/s to a JBOD 3TB setup. This burst last for about 8 seconds and then back to a 10 min delay before the next burst.

Before the drive developed this symptom Mac Fan Control was installed to minimize heat but despite this effort, drive performance continuously degraded. In fact, from time to time an audible click has now made its presence known, usually a dire warning. So far it’s keeping its distance.

smartmontools is another great tool you can install via Homebrew and can provide more info about your drive’s SMART failures. Their About Home page has this to say:

The smartmontools package contains two utility programs (smartctl and smartd) to control and monitor storage systems using the Self-Monitoring, Analysis and Reporting Technology System (SMART) built into most modern ATA/SATA, SCSI/SAS and NVMe disks. In many cases, these utilities will provide advanced warning of disk degradation and failure.

Brew install smartmontools

When using it type:

smartctl -a /dev/diskU

U is the unit number. -a displays all info.

At the moment the command above yields the following error:

A mandatory SMART command failed: exiting.

Wiping a failed drive — Warranty follow-up

This drive is inside warranty so finding a way to wipe the data as clean as possible is somethig I am looking into. I am not fond of my data being exposed.

In terms of smartctl reporting anything back for the affected drive, it reached a point where the drive could no longer report anything. In fact the drive was even unable to display its’ partitions (slices). The decision was taken to shutdown the computer overnight afterwhich the drive showed an inability to mount in the Finder but was able to report back all of its’ partitions and SMART info via the smartctl (smartmontools) command and diskutil respectively.

smartctl report

The deatils of the SMART status are below if you care to read them. Some of it is not easily understood, not for me anyway but there are some interesting tidbits, especially the warning I marked in bold italics.

$ smartctl -a /dev/disk1smartctl 6.5 2016-05-07 r4318 [Darwin 15.6.0 x86_64] (local build)Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org=== START OF INFORMATION SECTION ===Model Family:     Toshiba 3.5" DT01ACA... Desktop HDD
Device Model: TOSHIBA DT01ACA200
Serial Number: 85GNUHZHS
LU WWN Device Id: 5 000039 fe2c97734
Firmware Version: MX4OABB0
User Capacity: 2,000,398,934,016 bytes [2.00 TB]
Sector Sizes: 512 bytes logical, 4096 bytes physical
Rotation Rate: 7200 rpm
Form Factor: 3.5 inches
Device is: In smartctl database [for details use: -P show]
ATA Version is: ATA8-ACS T13/1699-D revision 4
SATA Version is: SATA 3.0, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is: Fri Feb 10 11:47:20 2017 CET
SMART support is: Available - device has SMART capability.
SMART support is: Enabled
=== START OF READ SMART DATA SECTION ===SMART Status command failed: Undefined error: 0
SMART overall-health self-assessment test result: FAILED!
Drive failure expected in less than 24 hours. SAVE ALL DATA.
Warning: This result is based on an Attribute check.
See vendor-specific Attribute list for failed Attributes.
General SMART Values:
Offline data collection status:
(0x84) Offline data collection activity was suspended by an interrupting command from host. Auto Offline Data Collection: Enabled.
Self-test execution status:
( 0) The previous self-test routine completed without error or no self-test has ever been run.
Total time to complete Offline data collection:
(14248) seconds.
Offline data collection capabilities:
(0x5b) SMART execute Offline immediate. Auto Offline data collection on/off support. Suspend Offline collection upon new command. Offline surface scan supported. Self-test supported. No Conveyance Self-test supported. Selective Self-test supported.
SMART capabilities:
(0x0003) Saves SMART data before entering power-saving mode. Supports SMART auto save timer.
Error logging capability:
(0x01) Error logging supported.
General Purpose Logging supported.
Short self-test routine recommended polling time:
( 1) minutes.
Extended self-test routine recommended polling time:
( 238) minutes.
SCT capabilities:
(0x003d) SCT Status supported.
SCT Error Recovery Control supported.
SCT Feature Control supported.
SCT Data Table supported.
SMART Attributes Data Structure revision number:
16
SMART Error Log Version:
1
Warning:
ATA error count 65535 inconsistent with error log pointer 1
ATA Error Count: 65535 (device log contains only the most recent five errors)CR = Command Register [HEX]
FR = Features Register [HEX]
SC = Sector Count Register [HEX]
SN = Sector Number Register [HEX]
CL = Cylinder Low Register [HEX]
CH = Cylinder High Register [HEX]
DH = Device/Head Register [HEX]
DC = Device Command Register [HEX]
ER = Error register [HEX]
ST = Status register [HEX]
Powered_Up_Time is measured from power on, and printed as DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes, SS=sec, and sss=millisec. It “wraps” after 49.710 days.

There was more info that smartctl displayed but it doesn’t display well due to the narrow columns on Medium so it’s pasted below.

Use Terminal to list the size of the .dmg file being recovered to

If you have quit the Finder and want to use the terminal to navigate to the drive being recovered to so that you can eventually find the size of the .dmg file that ddrescue is recovering to.

cd /Volumes && ls

In my case, ddrescue is rescuing to a drive called ‘TM’.

cd /Volumes/TM

List the files on the ‘TM’ drive in detail.

ls -lh

Using Bare Bones’ TextWrangler with the MAP file

Open the the MAP file in TextWrangler so that you can see it get updated in realtime. Obviously, don’t edit it while ddrescue is working.

The mapfile is an essential part of ddrescue’s effectiveness. Without a mapfile, ddrescue can’t resume a rescue, only reinitiate it.

Having the txt file display in TextWrangler or similar provides the utility of being able to scroll down. If you can scroll down then you know it has gone through some more data on the drive.

My MAP file is called failing_drve_backup.txt.

Alternatively you can issue something like the line below (adding four -v verbosity flags) where disk0 is the affected drive and disk1 is the destination drive. ddrescue will display, amongst other things the “time since last successful read: X” where X=time. I don’t know off hand if you need four verbosity flags for this line to display but I tend to add all four anyway.

sudo ddrescue -v -v -v -v /dev/disk0 /dev/disk1/image_bad_drive.dmg /dev/disk6/mapfile.txt

Finally you can also use the following line to get file system usage to stream as ddrescue does it thing, this Terminal window will show the time in the left hand side column. There are likely countless other methods to keep track but these are a few.

sudo fs_usage -w -f | grep ddrescue

Learn more about the MAP file structure.

Character Meaning 
'?' non-tried block
'*' failed block non-trimmed
'/' failed block non-scraped
'-' failed block bad-sector(s)
'+' finished block
And here is an example mapfile:
# Mapfile. Created by GNU ddrescue version 1.22
# Command line: ddrescue -d -c18 /dev/fd0 fdimage mapfile
# Start time: 2015-07-21 09:37:44
# Current time: 2015-07-21 09:38:19
# Copying non-tried blocks... Pass 1 (forwards)
# current_pos current_status current_pass
0x00120000 ? 1
# pos size status
0x00000000 0x00117000 +
0x00117000 0x00000200 -
0x00117200 0x00001000 /
0x00118200 0x00007E00 *
0x00120000 0x00048000 ?

Final thoughts

It’s been a pleasure writing this. Keep in mind that ddrescue can take a long time to complete. I hope you learned something. It took a few days to actually write this up as I am not a writer by trade nor a Terminal guru but ddrescue is worth looking into and if you do end up using it consider donating to the developer, Antonio Diaz Diaz who has built a really incredible tool.

--

--