![如何在磁盘清零时忽略写入错误?](https://linux22.com/image/13138/%E5%A6%82%E4%BD%95%E5%9C%A8%E7%A3%81%E7%9B%98%E6%B8%85%E9%9B%B6%E6%97%B6%E5%BF%BD%E7%95%A5%E5%86%99%E5%85%A5%E9%94%99%E8%AF%AF%EF%BC%9F.png)
假设您要将故障硬盘清零。您希望用零覆盖尽可能多的内容。您不想要的是:进程在第一次写入错误时中止。怎么做?
AFAICS,plaindd
仅提供忽略读取错误的选项。因此,像
dd if=/dev/zero of=/dev/disk/by-id/lousy-vendor-123 bs=128k
是不足够的。
ddrescue
似乎更擅长忽略错误 - 但是它的最佳命令行是什么?
我尝试使用 GNU ddrescue:
ddrescue --verbose --force --no-split /dev/zero /dev/disk/by-id/lousy-vendor-123
答案1
我更喜欢badblocks
使用破坏性写入模式。它写道,当遇到错误时,它会继续这样做,最后它会告诉您这些错误在哪里,这些信息可能会帮助您决定下一步要做什么(它会混合吗?)。
# badblocks -v -b 4096 -t random -o badblocks.txt -w /dev/destroyme
Checking for bad blocks in read-write mode
From block 0 to 2097151
Testing with random pattern: done
Reading and comparing: done
Pass completed, 52105 bad blocks found. (0/52105/0 errors)
以及阻止列表:
# head badblocks.txt
2097000
2097001
2097002
2097003
2097004
之后磁盘上还剩下什么:
# hexdump -C /dev/destroyme
00000000 be e9 2e a5 87 1d 9e 61 e5 3c 98 7e b6 96 c6 ed |.......a.<.~....|
00000010 2c fe db 06 bf 10 d0 c3 52 52 b8 a1 55 62 6c 13 |,.......RR..Ubl.|
00000020 4b 9a b8 d3 b7 57 34 9c 93 cc 1a 49 62 e0 36 8e |K....W4....Ib.6.|
请注意,这并不是真正的随机数据 - 模式是重复的,因此如果您跳过,1MiB
您会再次看到相同的输出。
它还会尝试通过读回数据来进行验证,因此,如果您有一个声称写入成功但在读回时返回错误数据的磁盘,它也会找到这些错误。 (确保在坏块运行时没有其他进程写入磁盘,以避免误报。)
当然,对于严重损坏的磁盘,这可能需要很长时间:没有代码可以使其完全跳过有缺陷的区域。实现这一目标的唯一方法badblocks
是使用更大的块大小。
我不确定ddrescue
这是否会更好;它应该在另一个方向上做到这一点(尽快恢复尽可能多的数据)。您可以通过指定第一个/最后一个块来手动执行 dd/ddrescue/badblocks...
答案2
如果磁盘是不是通过 USB 连接,然后考虑使用hdparm
(版本 > 9.31)执行ATA 安全擦除磁盘的。此命令使驱动器的固件擦除磁盘的内容,包括坏块。
警告:使用正确的驱动器号 - 我已/dev/sdX
作为示例显示 - 不要只是复制/粘贴。
首先,检查它是否理解 ATA 命令(过去十年或更长时间制造的大多数驱动器都应该理解):
$ sudo hdparm -I /dev/sdX
.
# lots of other info here...
.
Security:
Master password revision code = 65534
supported
not enabled
not locked
not frozen
not expired: security count
supported: enhanced erase
202min for SECURITY ERASE UNIT. 202min for ENHANCED SECURITY ERASE UNIT.
摘录的最后两行表明它是受支持的。
因此,为驱动器添加密码(显然是一个要求):
$sudo hdparm --user-master u --security-set-pass p /dev/sdX
security_password="p"
并删除:
$sudo hdparm --user-master u --security-erase p /dev/sdX
security_password="p"
/dev/sdX:
Issuing SECURITY_ERASE command, password="p", user=user
有关此过程的更多信息可用这里。
答案3
我在这里看到四个可行的答案:
方法
hdparm
发布者加雷思·红如果您直接连接到计算机,这可能是最好的。但显然,如果你尝试通过 USB 连接,你的驱动器可能会变砖。如果您正在为即将处置的驱动器执行此操作,那么这可能是一件好事。但是,您可能希望在丢弃之前确保擦除。技术报道者imz——伊万·扎哈里亚切夫会起作用,但可能会很慢。我建议如果您不希望数据可恢复,请使用
/dev/urandom
而不是/dev/zero
;例如,dd iflag=fullblock oflag=direct conv=noerror,notrunc if=/dev/urandom of=/dev/sdX
我会建议反对以下内容。对于更快地执行相同操作的方法,请使用 maxschlepzig 报告的技术(在问题中):
ddrescue --verbose --force --nosplit /dev/urandom /dev/sdX
这会比
dd
命令快,但不如命令快hdparm
。请参阅下文,为什么我不推荐此...该
badblocks
命令也可以工作,但是您不能以这种方式随机化数据,而且它会非常慢。
最后,如果我没有指出人们想要完全擦除磁盘的首要原因是他们即将处置它,那就是我的失职。在这种情况下,如果您还没有这样做,您可能需要先尝试恢复磁盘。如果您读取一个块并返回 I/O 错误,那么下次您写入同一块时,磁盘将尝试从保留列表中重新分配不同的块。一旦保留列表已满,您将在写入时遇到 I/O 错误。那是你真正应该丢弃驱动器的时候。
所以你可以做一些简单的事情,比如:
dd if=/dev/sdX of=/dev/null conv=noerror
然后,重写坏块,就像这样:
dd if=/dev/zero of=/dev/sdX bs=128k
如果这个命令有效,如果你勇敢的话,你可以重新格式化你的磁盘并再次使用它。
或者,您可以badblocks
在磁盘上运行该命令两次。第二次应该报告没有坏块......
badblocks -v -s -w -t random /dev/sdX
badblocks -v -s -w -t random /dev/sdX
这将需要更长的时间,但更可靠。
还值得注意的是,除了命令之外,没有任何技术真正执行安全擦除hdparm
。还记得所有那些坏块吗?这些仍然保留着一些基本完好的原始数据。数据恢复专家可以访问这些内容以查看硬盘驱动器上以前的少量内容。
关于 ddrescue 以及我为什么建议反对它,我有以下解药:
问题是 ddrescure 太擅长忽略错误了。我的硬盘与 dd 一致,在 102 GB 时写入速度下降,并在 238 GB 时开始产生写入错误。令我印象深刻的是,ddrescue 继续以恒定的速度搅动磁盘,甚至没有报告任何错误。 17 小时后,当它达到 1300 GB 时,我碰巧注意到驱动器灯本身停止闪烁。快速检查发现整个 USB 外壳已脱机。我将驱动器从支架中拔出。我注意到 ddrescue 很高兴地报告它仍在复制,没有错误,即使我手中有磁盘。我将磁盘插入另一台机器,发现它现在变成了一块砖。
我不会责怪 ddrescue 使驱动器变砖。驱动器出现故障并且会变成一块砖。我只是发现令人不安的 ddrescue 甚至没有给出它忽略了多少写入错误的错误计数。在这种用法中,ddrescue 让您认为它已经完全成功,而不管所有写入失败。事实上,在减速的路段,它不应该能够继续全速行驶。该部分速度缓慢的原因是驱动器已重新定位许多块,导致访问该部分时进行大量查找。所以这可能就是 ddrescue 的输出变得虚构的时刻。
答案4
dd conv=notrunc
可能对我有用。
其中提到的
dd conv=noerror
必须是读取错误(根据手册页)。两者结合起来并没有什么不好。
我将磁盘清零的完整命令如下所示:
dd iflag=fullblock oflag=direct conv=noerror,notrunc if=/dev/zero of=/dev/TARGET_DISK
bs=
在某些情况下可能还需要添加自定义。