简要总结

TL;DR: 不能。你无法修复硬盘上的物理坏道。盘片表面一旦划伤,损伤就是永久的。软件只能检测损伤,或请求固件把它隐藏起来。

  • 软件能修好吗? 不能。badblocks、smartctl 以及其他任何工具都只能检测或报告坏道。
  • 硬盘能自我修复吗? 部分可以。硬盘固件可以把坏道重映射到备用扇区,但这是隐藏损伤,不是治愈损伤。
  • 应该怎么做? 如果数据重要,先用 ddrescue 克隆磁盘,然后更换硬盘。如果只是测试盘,就观察坏道计数是否增长。

本文用真实命令和真实磁盘数据,说明 badblocks、SMART 和硬盘固件实际做了什么。

什么是坏道?

扇区是硬盘上最小的存储单位。可以把它想象成一本很大的笔记本里的一页。坏道就是硬盘再也无法可靠读取或写入的一页。

扇区变坏后,存储在那里的任何数据都有风险。现代硬盘内置了错误处理机制,但坏道一旦开始出现,通常意味着硬盘正在老化或已经发生物理损伤。

要点: 坏道并不总是立刻可见。操作系统可能直到尝试读取存放在坏位置的文件时才会报错。

坏道的两种类型

并非所有坏道都一样。理解它们的区别是本文最重要的部分。

软(逻辑)坏道

这类坏道是扇区中的数据损坏,但磁盘的物理表面完好。原因包括:

  • 硬盘写入数据时断电
  • 软件缺陷或恶意软件
  • 磁信号减弱或混乱

这类坏道有时可以通过用新数据覆盖该扇区来“修复”。物理磁盘没有损坏,只是上面的信息出错了。

硬(物理)坏道

这类坏道是盘片的实际表面受损。原因包括:

  • 读写磁头接触盘片(“磁头碰撞”)
  • 密封盘腔内部进入灰尘或污染物
  • 多年使用后的正常磨损
  • 制造缺陷

没有任何软件能治愈物理损伤。 软件只能请求硬盘使用备用扇区来隐藏损伤。盘片上的划痕会永久存在。

严重警告: 如果你的硬盘存在物理坏道,反复运行高强度测试实际上可能让问题更糟,因为这会继续折磨已经出问题的硬件。

测试盘:来自真实硬盘的数据

本文测试的是一块真实的 250 GB SATA 硬盘。以下是测试前系统看到的信息。

用 lsblk 检查磁盘布局

3.1.1 什么是 lsblk?

lsblk(“list block devices”)显示系统中所有块存储设备:硬盘、SSD、NVMe 盘及其分区。它还会显示哪些分区已挂载、挂载在哪里。这有助于你在运行破坏性命令前确认目标磁盘是否正确。

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda           8:0    0 232.9G  0 disk
└─sda1        8:1    0 232.9G  0 part
[...]

注意 sda 是一块 232.9 GB 磁盘,只有一个分区(sda1),并且未挂载。这可以安全测试。

如果它已挂载,应先卸载。这一点非常重要。

用 fdisk -l 显示分区布局和磁盘几何信息

3.2.1 什么是 fdisk -l?

fdisk 是 Linux 上的分区表操作工具。-l 标志表示“列出”,让它显示分区布局和磁盘几何信息,而不做任何修改。它会显示磁盘总容量、扇区数、扇区大小和分区边界。

$ sudo fdisk -l /dev/sda
Disk /dev/sda: 232.89 GiB, 250059350016 bytes, 488397168 sectors
Disk model: 045
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

这确认该磁盘有 488,397,168 个扇区,每个扇区 512 字节。这就是 badblocks 将扫描的总表面范围。

在 Linux 中用 badblocks 检查坏道

什么是 badblocks?

badblocks 是一个 Linux 工具,它通过向每个块写入测试模式、再读回并比较写入与读取的内容,来测试存储设备是否有损坏扇区。它是诊断工具,不是修复工具。它会告诉你哪些块不可靠,但不会修复它们。

badblocks -wsv 实际做什么?

sudo badblocks -wsv /dev/sda

逐项拆解:

警告:破坏性操作: -w 标志会擦除目标磁盘上的所有内容。没有确认提示。它会立即开始写入。只应在没有重要数据的磁盘上使用。

测试模式的含义

badblocks -w 不只是写零。它会依次使用多种测试模式:

  • 0xaa(二进制:10101010)
  • 0x55(二进制:01010101)
  • 0xff(二进制:11111111)
  • 0x00(二进制:00000000)

每种模式都会写入每个块,然后读回并比较。如果读取结果与写入不匹配,该块就会被报告为坏块。

badblocks 不做什么

badblocks 不直接控制或执行扇区重映射。它不修复物理磁盘表面。它只是读取和/或写入扇区,并报告 I/O 错误。不过,当执行写入操作时,硬盘自身的固件可能检测到故障扇区,并将其重映射到备用扇区。这种重映射由硬盘完成,而不是由 badblocks 完成。

手册页本身就警告不要直接使用它

请注意,badblocks 手册页明确建议不要直接运行它。它建议改用 e2fsck -c 或 mke2fs -c,它们会在内部以适合你文件系统的正确块大小调用 badblocks。

为什么手册不鼓励直接使用?

badblocks 产生的块号取决于块大小。默认是 1024 字节。如果你的文件系统使用不同的块大小(例如 4096 字节),而你没有传入 -b,那么输出中的块号并不指向你认为的那些块。通过 e2fsck -c 或 mke2fs -c 运行扫描,意味着块大小在构造上就是正确的。文件系统工具知道自己的块大小;你不一定知道。

数据存在时 -w 的安全替代方案

如果需要测试仍含数据的磁盘,请改用以下方式之一:

-f 标志: badblocks 通常拒绝在已挂载设备上运行,因为它可能导致系统崩溃或文件系统损坏。-f 标志会覆盖这一限制。手册自己的注释很值得记住:“如果你认为自己比 badblocks 程序更聪明,那你几乎肯定不是。” 请改为卸载设备。

读取 SMART 数据:这些数字意味着什么

即使 badblocks 报告没有错误,SMART 数据也会告诉你硬盘固件自身对其健康状况的了解。

什么是 smartctl?

smartctl 是 smartmontools 软件包的命令行接口。它读取几乎所有现代硬盘和 SSD 内置的 SMART(Self-Monitoring, Analysis, and Reporting Technology,自我监测、分析与报告技术)数据。

SMART 是硬盘内部的健康监测系统,跟踪磨损指标、错误计数、温度和预测性故障迹象。-a 标志让它打印所有可用信息。

在运行任何破坏性测试前,应始终检查硬盘内置的健康报告。

$ sudo smartctl -a /dev/sda
=== START OF INFORMATION SECTION ===
Device Model:     GB0250C8045
Serial Number:    9SF0HF1B
Firmware Version: HPG2
User Capacity:    250,059,350,016 bytes [250 GB]
Rotation Rate:    7200 rpm
...
SMART overall-health self-assessment test result: PASSED
...
Self-test execution status:      ( 121) The previous self-test completed having
the read element of the test failed.

这里已经出现矛盾:硬盘总体状态显示“PASSED”,但最近一次自检在读取操作中失败。这很常见。SMART 总体状态可能偏乐观,而单项测试会揭示真实问题。

运行你自己的 SMART 自检

sudo smartctl -t short /dev/sdb
sudo smartctl -t long /dev/sdb
sudo smartctl -l selftest /dev/sdb

你可以启动硬盘内置自检,而不进行任何破坏性操作。这些测试在硬盘固件内部运行,并将结果报告给 SMART。

$ sudo smartctl -t short /dev/sda    # Usually under 10 minutes
$ sudo smartctl -t long /dev/sda     # More thorough, tens of minutes
$ sudo smartctl -l selftest /dev/sda # View results of past tests

短测试检查电气和机械性能,并抽样读取操作。长测试扫描整个表面。两者都在后台运行;之后用 -l selftest 检查结果。

最重要的 SMART 属性

Backblaze 运营着最大的公开硬盘故障数据集之一,它监测 五个 SMART 属性 来预测故障。我们的测试盘报告了其中大部分属性:

45 个重映射扇区到底意味着什么

这块硬盘已经有 45 个扇区被固件永久退役,并用内部备用池中的备用扇区替换。这 45 个扇区是物理损伤。没有软件能恢复它们。现在唯一的问题是是否还会出现更多。

SMART 错误日志详情

错误日志显示同一位置反复出现读取失败:

Error 24 occurred at disk power-on lifetime: 9578 hours
Error: UNC at LBA = 0x0018f66b = 1635947
Commands leading to the error were:
READ DMA EXT
READ DMA EXT
READ DMA EXT
...
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
#1   Short offline       Completed: read failure       90%      9578         1635947

同一个逻辑块地址(LBA 1635947)出现在每次错误中。这是磁盘表面上一个具体位置,硬盘始终无法读取。短离线自检也在完全相同的位置失败。

SMART 漏掉 23% 的故障

关于 SMART 数据,最重要的注意事项在这里。Backblaze 公布的统计数据 显示,76.7% 的故障硬盘在上述五个关键属性中至少有一个大于零,但这意味着 23.3% 的故障硬盘完全没有显示 SMART 警告。在这些统计中,接近四分之一的硬盘在故障前从未触发这些标志。

SMART 是证据,不是保证:

SMART 检查通过只意味着目前尚未检测到坏情况。它不代表硬盘健康,也不能替代备份。一份干净的报告不等于一张健康证明。要把硬盘与它自己的历史比较,而不是与互联网上的表格比较。

运行 badblocks 测试

现在我们运行破坏性写入测试。由于这块硬盘没有重要数据,这样做是安全的。

$ sudo badblocks -wsv /dev/sda
Checking for bad blocks in read-write mode
From block 0 to 244198583
Testing with pattern 0xaa:  20.31% done, 1:55:02 elapsed, (0/0/0 errors)
# After more time passes, you might see errors appear:
Testing with pattern 0xaa:  45.12% done, 4:20:15 elapsed, (3/1/2 errors)

警告: 如前所述,-w 标志会立即开始向磁盘写入。只有在目标磁盘没有重要数据时才使用它。

如果硬盘已经在物理退化,一次完整的破坏性写入测试可能把它推向极限,使其彻底停止工作。对测试盘来说这可以接受,但值得反复强调。

理解错误计数器:(0/0/0)

进度行末尾括号中的三个数字是测试过程中的错误计数器。

保持耐心并使用电源保护: 完整破坏性测试可能耗时数小时。如果测试期间断电,你可能得到一块被部分擦除的硬盘和不完整的结果。尽可能使用 UPS,并让笔记本电脑保持接通电源。在我们的 250 GB 硬盘上,测试大约花了 9 小时。

测试之后会发生什么?

情况 A:没有发现坏块

如果 badblocks 在所有模式下完成且零错误,你可能会看到:

Pass completed, 0 bad blocks found. (0/0/0 errors)

这意味着磁盘表面通过了写入-读取-校验测试。但请记住,我们的测试盘在 SMART 历史中已经有 45 个重映射扇区。这些在我们开始之前就已经被固件隐藏了。测试只检查是否出现新问题。

情况 B:发现坏块

如果 badblocks 发现坏块,它会打印块号:

1635947
1635948
1635950
Pass completed, 3 bad blocks found. (3/0/3 errors)

注意块 1635947 与 SMART 错误日志中的 LBA 匹配。这是强有力的确认:硬盘固件和 badblocks 指向同一个物理位置。

坏块列表能做什么

你可以把列表保存到文件,并在创建新文件系统时告诉文件系统避开这些块:

7.3.1 什么是 mkfs.ext4?

mkfs.ext4 在分区上创建 ext4 文件系统。这是格式化分区以便 Linux 存储文件的过程。-l 选项(小写 L)让它读取坏块列表,并在文件系统数据结构中将这些块标记为不可用,这样你的文件永远不会写入这些物理位置。

sudo badblocks -wsv -o badblocks_list.txt /dev/sda
sudo mkfs.ext4 -l badblocks_list.txt /dev/sda1

-l 选项告诉 mkfs.ext4 在文件系统中把这些块标记为不可用。你的数据永远不会写入那里。但请记住,这是变通方法,不是修复。

谁真正执行重映射?

这是人们所谓“磁盘修复”中最容易被误解的部分。

关于重映射的真相:

当 badblocks -w 写入坏扇区时,硬盘固件可能决定将其重新分配到备用扇区。但这只在固件于写入操作期间检测到问题时才会发生。badblocks 并不命令重映射。它只是写入数据,由硬盘内部的大脑决定怎么做。

如果你的硬盘仍有数据怎么办?

本文全程假设你的硬盘没有重要数据,这是运行 badblocks -w 的唯一安全条件。如果你的硬盘包含重要文件,不要对它运行破坏性测试。对故障硬盘的每一次读写操作都是风险。

黄金法则:先镜像,后测试

如果数据重要,操作顺序是:

  1. 使用专为损坏介质设计的工具,将硬盘克隆到健康硬盘或镜像文件
  2. 验证克隆并从中恢复文件
  3. 只有在这之后,才对原盘运行测试(如果你仍关心它的状况)

8.1.1 什么是 ddrescue?

ddrescue(GNU ddrescue)是一个数据恢复工具,用于把一个块设备的数据复制到另一个块设备,专为故障硬盘设计。

与 dd 不同,它会智能跳过坏扇区、重试失败区域,并保留一个 mapfile,以便恢复会话中断后继续。它先读取容易的部分,再回头处理损坏区域,从而尽量减少对故障硬盘的压力。

$ sudo ddrescue -f -n /dev/sda /dev/sdb rescue.mapfile
# -f = force (overwrite output)
# -n = skip scraping phase initially (faster first pass)
# rescue.mapfile = progress log you can resume from
# Then retry the bad sectors more aggressively:
$ sudo ddrescue -d -r3 /dev/sda /dev/sdb rescue.mapfile
# -d = direct disc access (bypass kernel cache)
# -r3 = retry bad sectors up to 3 times

停止向故障硬盘写入:

对故障硬盘的每一次写入,都可能覆盖本可恢复的内容,并让已经在挣扎的机械结构承担更多工作。如果数据重要,先克隆,再调查。在存有珍贵数据的硬盘上运行 badblocks -w,就像你还站在桥上时却对一座正在燃烧的桥做压力测试。

结论:你真的能修复坏道吗?

简短回答:不能。你无法修复坏道。

badblocks 不行,smartctl 也不行。任何你能在计算机上运行的软件或工具都不行。扇区一旦物理损坏,就会永久损坏。

软(逻辑)坏道:“可纠正”,不是“已修复”

如果扇区包含损坏数据,但物理表面完好,用新数据覆盖它可以让它重新可读。但你并没有“修复”这个扇区。你只是用新数据覆盖了旧的损坏数据。扇区本身从未物理损坏。

硬(物理)坏道:永久损坏

如果盘片物理表面被划伤、污染或损坏,没有软件能治愈这种损伤。划痕不会因为你运行了一条命令就消失。

硬盘固件做的是从内部备用池中取一个备用扇区替换坏扇区,从而隐藏损伤。损伤仍然存在。你只是再也看不到它了。

软件实际做什么,人们以为它做什么

软件能做的是检测与报告:用 badblocks 扫描块、用 smartctl 读取 SMART 属性与错误日志,以及在写入时由固件触发重映射。它做不到的是恢复盘片上的物理损伤,也无法让已经被固件退役的扇区重新可用。覆盖新数据只能让逻辑损坏的扇区重新可读。

如果硬盘有坏道应该怎么做

扇区一旦因物理损伤变坏,就会永久坏下去。你最多只能:

  1. 检测它(用 badblocks 或 SMART)
  2. 隐藏它(用固件重映射或文件系统坏块列表)
  3. 更换硬盘(在更多扇区失效之前)

如果数据重要,先用 ddrescue 克隆磁盘,然后更换硬盘。如果磁盘只是用于测试且没有重要数据,你可以继续使用,同时监测坏道计数是否增长。但你并没有“修复”任何东西。你只是管理了症状。

SSD 与 NVMe 的差异

本文的示例是一块转动式硬盘。重映射扇区、待处理扇区这类属性描述的是盘片和读写磁头的老化与损伤,SSD 没有盘片和磁头,这些成因不适用。

smartctl 同样可以读取 SSD 与 NVMe 设备上的 SMART 数据,但属性集合与故障模式与机械硬盘不同。-w 的破坏性写入在任何块设备上都会擦除数据,这一点不因介质类型而改变。

常见误解

  • “软件能修复坏道。” badblocks 和 smartctl 只能检测或报告,物理损伤不会被治愈。
  • “SMART 显示 PASSED,硬盘就没问题。” 总体状态可能偏乐观,自检和错误日志可能已经记录了失败;而且 SMART 会漏掉一部分故障。
  • “固件重映射等于修复。” 重映射只是用备用扇区把坏扇区藏起来,损伤仍然留在盘片上。
  • “坏块列表修好了硬盘。” 那只是让文件系统避开这些块,同样是变通方法。

什么时候应该更换硬盘?

可以继续使用(需谨慎)

重映射扇区为零、待处理扇区为零、ATA 错误为零,并且 badblocks 干净通过。硬盘健康。

密切监测

有少量重映射扇区(例如我们的 45 个),但稳定且不增长。硬盘可能还能用几年,但如果没有备份,不要在上面存放关键数据。

立即更换

重映射扇区快速增长、当前待处理扇区大于零、反复出现 ATA 错误、咔嗒声,或 badblocks 每次测试都发现新的坏道。硬盘正在主动失效。

如何检查计数是否增长

在 badblocks 测试前后运行 smartctl,然后比较:

$ sudo smartctl -a /dev/sda | grep -E "Reallocated|Pending|Uncorrectable"
5 Reallocated_Sector_Ct   ... 45
197 Current_Pending_Sector  ... 0
198 Offline_Uncorrectable   ... 5

如果 Reallocated_Sector_Ct 在 badblocks 之后上升,说明固件在测试期间发现了新的坏道并替换了它们。这证明硬盘仍在退化。

还有一件事:检查线缆

并非所有磁盘错误都意味着硬盘将死。非零的 UDMA_CRC_Error_Count(SMART 属性 199)通常表示 SATA 线缆不良或连接松动,而不是硬盘故障。在丢弃硬盘之前,先尝试更换线缆和端口。我们的测试盘显示 CRC 错误为零,所以问题确实在硬盘上。

资源: