通过设置 of=if 使用‘dd’来“恢复”硬盘是否安全?

通过设置 of=if 使用‘dd’来“恢复”硬盘是否安全?

为了防止由于以下原因导致的一些磁盘腐烂源:磁通量随时间的变化,我想读取并重写磁盘上的所有数据。似乎有一个“dd”命令可以执行此操作。具体来说:

dd if=/dev/sda of=/dev/sda

我对此命令有一些疑问,具体如下:

  1. 无论文件系统如何它都是安全的吗?
  2. 这个过程是否会按照我期望的方式进行,即读取一个扇区,然后立即重写它?
  3. 这是否具有预期的实际效果,或者用这种方法来防止某些形式的钻头腐烂只是骗人的把戏?

答案1

经验方法。我决定进行测试。简短回答:测试未显示该程序不安全。


测试平台

uname -a

Linux foobar 3.2.0-4-amd64 #1 SMP Debian 3.2.86-1 x86_64 GNU/Linux

摘录自smartctl -a /dev/sdc

Model Family:     Western Digital Caviar Blue EIDE
Device Model:     WDC WD5000AAKB-00H8A0
Firmware Version: 05.04E05
User Capacity:    500,107,862,016 bytes [500 GB]
Sector Size:      512 bytes logical/physical

SMART 还显示磁盘健康。

它是通过 USB 桥接器(至 USB 2.0 集线器)连接的。lsusb | grep SATA

Bus 001 Device 003: ID 152d:2509 JMicron Technology Corp. / JMicron USA Technology Corp. JMS539 SuperSpeed SATA II 3.0G Bridge

一个分区,几乎没有未分配的空间。fdisk -l /dev/sdc

Disk /dev/sdc: 465,8 GiB, 500107862016 bytes, 976773168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x202b0b89

Device     Boot Start       End   Sectors   Size Id Type
/dev/sdc1        2048 976773167 976771120 465,8G 83 Linux

健康的 ext4 文件系统,已卸载。file -s /dev/sdc1

/dev/sdc1: Linux rev 1.0 ext4 filesystem data, UUID=… (extents) (large files) (huge files)

文件系统使用率约为 20%,但是:

  • 它已经被广泛使用了,所以可用空间肯定不是全零;
  • 无论如何,我不会依赖文件系统,我计算了md5sum整个设备(见下文)。

测试

首先我保存了整个设备内容的校验和:

md5sum -b /dev/sdc > sdc.before.md5
# the throughput was about 24 MB/s

实际dd-ing:

dd if=/dev/sdc of=/dev/sdc
# took 800 minutes, 10,4 MB/s

dd if=/dev/sdc of=/dev/sdc bs=128M conv=sync
# 630 minutes, 13,2 MB/s

dd if=/dev/sdc of=/dev/sdc bs=512 conv=sync
# 795 minutes, 10,5 MB/s

每次dd我跑完之后sync,然后md5sum -b /dev/sdc所有校验和均匹配sdc.before.md5

我也喜欢它strace dd if=/dev/sdc of=/dev/sdc,它让我的终端充斥着类似这样的行:

read(0, "]\203\0\0]\203\1\0]\203\2\0]\203\3\0]\203\4\0]\203\f\0]\203\r\0]\203\30\0"..., 512) = 512
write(1, "]\203\0\0]\203\1\0]\203\2\0]\203\3\0]\203\4\0]\203\f\0]\203\r\0]\203\30\0"..., 512) = 512

或(对于较大的bs

read(0, "A\260_4\245\316\273\321p\203\331\250\3022\354\303\6\30\233\366\345\237\303\244\fx\10@=0\221+"..., 134217728) = 134217728
write(1, "A\260_4\245\316\273\321p\203\331\250\3022\354\303\6\30\233\366\345\237\303\244\fx\10@=0\221+"..., 134217728) = 134217728

结论和答案

  1. 无论文件系统如何它都是安全的吗?

校验和保持不变,这里没有任何特定于文件系统的内容。用相同数据覆盖数据应该是安全的。

注意:对于直接覆盖扇区的磁性驱动器来说,这是正确的。另一方面,SSD(我不确定是否所有 SSD 都是这样)需要先擦除一个扇区(或一次擦除多个扇区)才能再次写入。同一个逻辑扇区可能会写入不同的物理“单元”等。如果发生电源故障,这可能会导致数据损坏(也可能不会,我对 SSD 中的预防措施知之甚少)。您提到了磁通量,所以我猜 SSD 无论如何都超出了范围。

  1. 这个过程是否按照我期望的方式进行,即读取一个扇区,然后立即重写它?

strace显示了确实发生的情况。缓冲区可能会延迟写入,但似乎每个读取的扇区迟早都会被重写。

我可以想到一种“优化”(在操作系统或硬盘固件中),它会将写入请求与缓存的读取进行比较,如果数据已经存在,可能会将写入视为不必要的而丢弃。这可能会使您的程序变得毫无意义。然而,这似乎不太可能,因为:

  • 除非你故意希望它发生,否则这种匹配很少会发生;
  • 缓存不够大,对于大值来说没有区别bs

因此,如果有疑问,只需使用大号即可bs。大号bs对性能也有好处。

  1. 这是否具有预期的实际效果,或者用这种方法来防止某些形式的钻头腐烂只是骗人的把戏?

我同意其中一条评论:

它确实会重写每个扇区,因此大概这就是所谓的位腐烂的“解决办法”。

不过,为了在实践中证实这一点,我们需要对许多磁盘(有些是“恢复活力的”,有些不是)进行长期的统计分析。我的单一测试无法回答这个问题。

相关内容