磁盘清零时如何忽略写入错误?


19

假设您要将故障硬盘归零。您希望尽可能用零覆盖。您不想要的是:进程在第一个写错误时中止。怎么做?

AFAICS dd仅提供了一个忽略读取错误的选项。因此,类似

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
dd conv=noerror我不确定这可能是GNU扩展。无论如何,它都可以解决问题。SATA告诉驱动器自己擦除的答案值得研究,以擦除整个驱动器。
彼得·科德斯

1
@ PeterCordes,GNU dd文档的手册页noerror为“读取错误后继续” ...
maxschlepzig 2015年

1
dd conv=noerrorist POSIX标准,但它可能真的很慢
schily

2
dd conv=noerror必须用于读取错误(根据手册),而不是写入错误。与结合使用conv=notrunc并没有什么不好,它对我而言忽略了写入错误。unix.stackexchange.com/a/229379/4319
imz-伊万·扎哈拉雅舒夫(Ivan Zakharyaschev)2015年

对HDD的简单写入操作(例如using dd if=/dev/zero of=/dev/sdX)将不会执行任何磁盘读取操作。您为什么认为dd命令“不够”?您遇到什么“错误”?
锯末

Answers:


12

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时,没有其他进程写入磁盘,以避免误报。)

当然,对于严重损坏的磁盘,这可能会花费太长时间:没有代码会使其完全跳过有缺陷的区域。达到此目的的唯一方法badblocks是使用更大的块大小。

我不确定ddrescue这是否会更好;它应该从另一个方向进行(尽快恢复尽可能多的数据)。您可以通过指定第一个/最后一个块来手动为dd / ddrescue / badblocks做...


1
如果我用的-t random还是-t 0-不badblocks然后就去做一个写通?查看手册页-似乎没有-t它就会进行4次传递(对于'0xaa,0x55​​、0xff,0x00')。
maxschlepzig

2
对于-t您在命令行上提供的每一项,它都会执行一次传递。如您所说,默认值为4次传递。
frostschutz

13

如果通过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

有关此过程的更多信息,请参见此处


如果幸运的话,这可以在USB上运行,并且USB <-> SATA桥可以通过非标准SATA命令传递(并且Linux驱动程序+ hdparm知道如何在该型号上执行此操作)。此外,对于编写示例来说,这样做/dev/sdX是件好事,因为如果有人在粘贴和自定义时错过了该示例,则不会有问题。
彼得·科德斯

@Peter Cordes-除非您有24个磁盘...不,愚蠢的我!谢谢,我将其更改为sdX,它将教我急于解决问题!
garethTheRed

2
链接的页面使用此方法列出了许多与硬件/固件有关的警告……有点吓人
maxschlepzig

它确实显示了很多警告!我只能说它对我没有任何麻烦。
garethTheRed

2

我在这里看到四个可行的答案:

  1. 如果您直接连接到计算机,则由garethTheRed发布hdparm方法可能是最好的。但是,显然,如果您尝试通过USB连接它,则可以使驱动器变砖。如果您要对要处理的驱动器进行此操作,那可能是一件好事。但是,您可能希望在丢弃前确保擦除安全。

  2. imz-Ivan Zakharyaschev报告的技术可以使用,但是可能很慢。我建议如果您不希望数据可恢复,请使用/dev/urandom代替/dev/zero; 例如,

    dd iflag=fullblock oflag=direct conv=noerror,notrunc if=/dev/urandom of=/dev/sdX
    
  3. 我建议以下几点。对于执行相同操作的更快的东西,请使用maxschlepzig报告的技术(在问题中):

    ddrescue --verbose --force --nosplit /dev/urandom /dev/sdX
    

    这将比dd命令快,但不如hdparm命令快。见下文为什么我不推荐这个...

  4. 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的输出变为虚构的点。


1
“要安全擦除,您需要使用随机数据多次覆盖同一块。” -您是否可以通过参考来证实您的主张(即经过同行评审的文章,其中显示了现代硬盘上归零数据的恢复)?另外,硬盘固件是一个黑匣子。您怎么知道ATA安全删除命令不只是实现为每个扇区写零模式?
maxschlepzig

相反。看起来在2006年,有许多研究表明,现代驱动器不再需要老式的多次写入,因为现代驱动器存储的数据如此密集,以至于一次写入同样有效。
user6856

1
dd conv=notrunc

可能对我有用。

提到的

dd conv=noerror

必须用于读取错误(根据手册)。结合两者没有什么不好。

我用于将磁盘清零的完整命令如下所示:

dd iflag=fullblock oflag=direct conv=noerror,notrunc if=/dev/zero of=/dev/sda

bs=某些情况下,可能还需要添加自定义。


1

使用一种快速成熟的方法sdd

如果您只想销毁所有内容,请致电:

sdd -inull bs=1m of=/dev/rdsk/cXdXtXp0 -noerror

始终使用“原始”磁盘驱动程序界面。

如果您想修复磁盘并保留尽可能多的旧内容,请致电:

sdd if=/dev/rdsk/cXdXtXp0 of=/dev/rdsk/cXdXtXp0 bs=1m -noerror

这将在512字节级别将所有不可读的块替换为零。您可能想通过修改重试次数try=#,默认值为2。

请注意,sdd它比dd发生错误时要快,因为它首先尝试使用提供的块大小进行读取,而在发生错误时,它以512字节进行读取。如果存在读取错误,则sdd会进行随机查找和虚拟读取,以使驱动器的固件稳定下来。

增强的错误恢复功能是在1980年代开发的,当时我为第二大的Sun Microsystems OEM工作。

Sdd源代码包含在schily工具中:

http://sourceforge.net/projects/schilytools/files/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.