Dead, dead, dead… It was the hard drive after all
A few days ago my MacBook Pro wouldn’t boot. Dropping down to single-user mode, I ran fsck and it found lots of errors. Perhaps foolishly, I tried to repair the errors multiple times. At the end of each run it would report that the drive could not be repaired. It looks like the disk problem I had earlier was a real disk problem and not just a bad image. Now I wish I hadn’t wasted so much friggin’ time reinstalling Tiger, upgrading to Leopard, installing apps, etc.
At least I have a reasonably recent backup. It’s only been a couple of days and yet I already wish I had taken the time to use the new Time Machine feature.
So I thought I would try to recover whatever I could from the drive before sending the machine back to Apple. Here was my basic process:
- Get my older PowerBook and connect it to the MacBook Pro with a firewire cable
- Boot the MacBook Pro into target disk mode by holding “t” while it was booting
- Wait 5 minutes while Leopard tries to fix the drive. It would then give up and mount it read-only, showing a nice message box that says “You’d better get your data off!”
- Use rsync to get a few files off until it hit a bad file and would get hung.
- Wait for 5 minutes until a read error would occur. Cancel rsync and unmount the drive.
- Reboot the machine to unwedge it, and resume the copying, skipping over the bad file.
I did figure out a way to make this process faster. The first delay can be overcome by manually mounting the drive before Leopard decides to try to mount it and fix the problems. I wrote this script to beat the OS, mounting the drive read-only:
#!/usr/bin/perl
print "Waiting for disk...\n";
do {
$result = `mount -v -t hfs -r /dev/disk1s2 /Users/coppit/Desktop/oldmac 2>&1`;
} while ($result =~ /(No such file|Permission denied)/);
if ($result =~ /Resource busy/) {
print $result;
do {
$result = `mount -v -t hfs -r /dev/disk1s2 /Users/coppit/Desktop/oldmac 2>&1`;
sleep 1;
} while ($result =~ /Resource busy/);
}
print $result;
Basically I would start this script, then boot up the other computer. Oh yeah, you have to create the “oldmac” directory ahead of time.
Now with regard to the second delay, all you have to do is power down the MacBook Pro. In this case you’ll get a “you forgot to unmount” error which can be ignored. But at least you don’t have to wait for the OS to determine there was a read error.
Finally, here’s what I did for the copy command:
~/desktop/remount && rsync --exclude-from=/Users/coppit/Desktop/excludelist -avu /Users/coppit/Desktop/oldmac/Users/coppit ~/Desktop/recovered
As you can see, I called my remount script and then did the copy. In this case I am copying my home directory into ~/Desktop/recovered. Whenever the copy would hang, I would put the filename (and perhaps part of the path) into the excludelist file, CTRL-c to abort the copy, power down the MacBook Pro, up-arrow to get the above command back, press enter, then power up the Macbook Pro.
With this process I was able to fairly quickly bypass bad files and get off all my important data. If I was really motivated I would have automated the creation of the excludelist file by watching the transfer speed during the copy operation. Then all I would have to do would be to power cycle the other computer at the appropriate times…