这个答案是关于磁盘的,固态硬盘(SSD)则不同。此外,这是一个没有数据(或者你不打算保留的数据)的磁盘;如果你的磁盘上有重要数据,请参考我对“我能用单个命令修复硬盘上的坏扇区吗”这个问题的回答。
自至少90年代末以来制造的磁盘可以自行处理坏扇区。简而言之,当磁盘在读取时发现扇区“弱”,但ECC足以恢复数据时,它会通过透明地将其替换为备用扇区来处理。在写入时,如果磁盘发现扇区标头损坏,或者在先前的读取中检测到扇区损坏但数据无法恢复,它也会进行替换。
磁盘固件通常允许您通过SMART属性来监控此过程(至少计数)。通常会有重新分配扇区的计数以及两个待处理的计数(发现读取错误、ECC失败,尚未写入)。
有两种方法可以使磁盘注意到坏扇区:
使用smartctl -t offline /dev/sdX命令告诉磁盘固件进行离线表面扫描。然后,你只需让磁盘保持空闲状态(完全不操作会最快),直到扫描完成(在smartctl -c /dev/sdX中检查"离线数据收集状态")。这通常会更新SMART中的"离线无法纠正"计数。(注意:驱动器可以配置为定期自动运行离线检查。)
让Linux读取整个磁盘,例如badblocks -b 4096 -c 1024 -s /dev/sdX。这通常会更新SMART中的"当前待处理扇区"计数。
以上两种方法都可能增加重新分配扇区计数——这是情况(b),ECC恢复了数据。
现在,要恢复这些扇区,你只需要向它们写入数据。通常情况下,这可以简单地通过使用命令pv -pterba /dev/zero > /dev/sdX(或者只用cat或dd)来实现但是你计划将它们作为RAID阵列的一部分。RAID初始化将会写入整个磁盘,所以这样做是没有意义的。唯一的例外是磁盘的开头和结尾——可能会错过几十兆字节的数据(由于对齐、标头等原因)。所以:
disk=/dev/sdX
end=$(echo "$(/sbin/blockdev --getsize64 "$disk")/4096-32768" | bc)
dd if=/dev/zero bs=4096 count=32768 of="$disk" # first 128 MiB
dd if=/dev/zero bs=4096 seek="$end" count=32768 of="$disk" # last 128 MiB
我想我成功避免了上面那个很容易犯的错误,所以应该会清空磁盘的前128MiB和后128MiB。然后让mdadm raid init写入剩下的部分。如果你愿意的话,将整个磁盘清零是无害的(除了一点点磨损和浪费时间)。
另外,如果你的硬盘支持的话,可以执行smartctl -l scterc,40,100(或者其他数字),告诉硬盘你希望它更快地放弃纠正读取错误——40代表4秒。这两个数字分别表示读取错误和写入错误;通过奇偶校验,mdraid可以轻松纠正读取错误(并将失败的扇区重新写回硬盘以进行重新分配)。然而,写入错误将导致硬盘从阵列中退出。
附注:务必注意已重分配扇区计数。该属性变为失败状态是个坏消息。如果它不断增加,那也是个坏消息。
附注2:确保定期对RAID阵列进行扫描(读取每个扇区并验证所有奇偶校验)。许多发行版已经提供了一个每月运行的脚本来完成此操作。这将检测并修复任何新的坏块,否则很少读取的坏块可能会滞留,并最终导致重建失败。
围栏错误——一种由于未计算其中一个端点而导致的偏差错误。得名于“如果你在每3英尺放置一个围栏柱,那么9英尺的独立围栏有多少个围栏柱?” 正确答案是4;围栏错误是3,是因为没有计算开始或结束处的柱子。