如何使用dd修复输入/输出错误?

嗨,我正在尝试修复我的Windows 7系统,因为硬盘坏了,但它仍然能运行。
我正试图将所有数据复制到一个新的驱动器上,以便重新安装Windows 7。这个驱动器叫做SQSERVICE。
我无法完全复制 - 请参见下面的内容:
$ sudo dd if=/dev/sdc1 of=/dev/sda1
dd: reading `/dev/sdc1': Input/output error
11233976+0 records in
11233976+0 records out
5751795712 bytes (5.8 GB) copied, 187.731 s, 30.6 MB/s

如何修复这个“输入/输出错误”?

1@Gertvddijk 感谢您修正我的拼写问题,我来自荷兰,仍在努力学习英语。 - Erazer
4个回答

你自己说了:你的硬盘坏了。你可以尝试使用ddrescue,它可能能够绕过损坏的路径进行工作。但要小心,这样做可能会丧失数据。
从备份中恢复会更容易 :) ddrescue的正确用法如下:
sudo apt-get install gddrescue
sudo ddrescue /dev/sdc1 /dev/sda1

或者,如果你想将stdout导入进度监控工具:
sudo ddrescue /dev/sdc1 /dev/sda1 | pv

是的,我说过那个,但是从备份中恢复它在那个驱动器上...而且这个驱动器只有扇区问题,那么我该如何使用那个命令呢?我只是一个新手Linux用户。 - Erazer
3你的备份是在同一驱动器上吗?你备份的时候还用同一个驱动器?!简直让人难以置信! - Dennis Kaarsemaker
1嗯,是同一个驱动器,但不在同一个分区上。唉,我有点蠢哭了,备份根本不重要。 - Erazer
ddrescue可以工作,但会创建一个无效的镜像文件,无法被fdisk读取,而dd则会创建一个有效的文件(尽管存在错误)。相当无用。 - The Quantum Physicist

我不知道这对任何人是否有用,但如果我在搜索中找到了这个页面,也许它能帮助其他人(除了那位希望几个月前解决了问题的原帖作者)。
在数据恢复方面,ddrescue可能是最好的选择,与原始问题所描述的“修复”错误/磁盘不同。正如Dennis建议的那样。
另外,您还可以挂载磁盘并复制文件。如果有大量空闲空间或者只想要某些特定文件,这种方法会快得多。警告:从Linux机器上执行此操作会丢失所有扩展属性,例如文件权限,因此对于操作系统文件来说是一个非常糟糕的选择,但对于用户文件来说是可以容忍的。从Windows上执行此操作应该会保留这些属性,但可能无法平稳处理错误,可能导致速度变慢。
另一种实际“修复”扇区而不仅仅是绕过它们的选项是重新分配坏扇区。如果您知道扇区号(在您的情况下,假设您的dd块大小和扇区大小都为512),只需运行以下命令,并针对每个新的坏扇区再次运行该命令:
hdparm –write-sector 11233976 –yes-i-know-what-i-am-doing /dev/sdb

警告:这将销毁该扇区上的数据。所以请确保您真的知道自己在做什么。如果无法读取该扇区,覆盖它将停止错误,但这意味着该扇区将包含垃圾数据,可能会损坏重要文件。
更多信息请参阅:http://www.sjvs.nl/forcing-a-hard-disk-to-reallocate-bad-sectors/ 如果您的硬盘有大量(可能达到数千个)坏扇区(可以看作是Current_Pending_Sector、Offline_Uncorrectable或Reallocated_Sector_Ct),或者如果它是新的并且还在保修期内,或者如果坏扇区数量持续增加,那么您应该替换硬盘。不要让别人告诉您重新分配可以修复硬盘的问题。它只能修复已知的坏扇区并消耗用于重新分配的扇区。如果硬盘容易产生更多坏扇区,问题将会一直出现,每次都会破坏一些数据。

虽然磁盘的某些部分损坏了,但你仍然可以复制磁盘上的好部分。
$ dd --help
...
 noerror   continue after read errors
...

sudo dd if=/dev/sdc1 of=/dev/sda1 conv=noerror

我遇到了一个带有IO错误的驱动器,而且在读取几分钟后,驱动器自己断开连接,但几秒钟后又重新连接上了,这也是为什么我使用disk/by-uuid,因为设备名称在此之后发生了变化。 我对Dennis' Answerthis one进行了扩展,使其无限运行。
#!/bin/bash
while [ true ]
do
    echo "start ddrescue"
    ddrescue -O  --retry-passes=3 /dev/disk/by-uuid/<uuid> /media/<other-disk>/data.img  /media/<other-disk>data_ddrescue_map
    echo "ddrescue end, sleep 30"
    sleep 30
done
    

这将使用带有映射文件的ddrescue,这样您可以重新启动程序,ddrescue将从之前的位置继续恢复数据到.img文件。
参数-O表示“在每次读取错误后重新打开输入文件”。
每次失败时,脚本会休眠30秒,然后再次尝试。经过将近一天的努力,我成功恢复了99%的数据,然后进展停滞不前。我让驱动器冷却下来,然后再次尝试,这次成功达到了100%。 警告:除非您自己终止它并对结果满意,否则该脚本将永远运行。 使用以下命令,您可以挂载创建的镜像文件以浏览文件:
sudo mkdir /media/data-image
sudo mount -o loop,ro /media/<other-disk>/data.img /media/data-image