4. 磁盘镜像制作:为什么需要磁盘镜像、使用dd命令制作镜像、处理坏道与读取错误

各位同学,咱们今天聊一个实操性很强的话题——磁盘镜像制作。说实话,我见过太多人一上来就对着坏盘跑数据恢复软件,结果越搞越糟。为什么?因为你每多读一次坏盘,它就可能多坏一点。这时候,镜像就是你最可靠的“保险单”。

4.1 为什么需要磁盘镜像?

直接对故障盘操作,风险太大了。我举个例子,你想想看:一块硬盘的磁头已经不稳定了,你还在上面反复扫描、尝试恢复文件。每一次读写,都可能让磁头刮伤盘片,或者让固件彻底崩溃。到时候,神仙也救不回来。

磁盘镜像的核心思路就一句话:在原始盘上只做一次完整的、只读的读取,然后把所有数据原封不动地复制到一个镜像文件里。之后所有的分析、恢复、尝试,都在镜像上进行。原始盘就可以安全地断电封存了。

核心原则:永远不要直接在故障盘上做数据恢复。先做镜像,再谈恢复。

我个人习惯,拿到一块故障盘的第一件事,就是用硬件写保护器(比如Tableau、DeepSpar)接上,确保系统只能读不能写。然后立刻开始做镜像。这一步做扎实了,后面才有底气。

镜像的好处还不止这些:

  • 可重复性:镜像文件可以无限次挂载、分析、实验。搞坏了?删掉重新解压一份就行。
  • 可迁移性:镜像可以拷贝到另一台机器、另一个系统上继续工作。原始盘可以安全存放。
  • 证据保全:在司法取证中,镜像的哈希值(MD5/SHA1)就是证据完整性的铁证。

4.2 使用dd命令制作镜像

说到制作镜像,Linux下的dd命令是当之无愧的瑞士军刀。它简单、直接、底层,几乎能处理任何块设备。Windows下也有类似的工具,比如dd for Windows或者FTK Imager,但原理都一样。

先看最基本的用法:

# 将/dev/sdb整个磁盘镜像到当前目录的disk.img文件
sudo dd if=/dev/sdb of=./disk.img bs=4M status=progress

这里解释一下参数:

  • if:输入文件,也就是源设备。比如/dev/sdb(整个磁盘)或/dev/sdb1(单个分区)。
  • of:输出文件,也就是镜像文件。可以是本地文件,也可以是另一个磁盘或网络位置。
  • bs:块大小。我建议用4M或8M,比默认的512字节快得多。但注意,如果盘有坏道,块太大反而容易卡死。
  • status=progress:显示进度。这个参数在较新的dd版本中才有,老版本可以用pv管道。

我的经验:做镜像前,先用fdisk -l或lsblk确认设备名。千万别搞错,if=/dev/sda和if=/dev/sdb写反了,你的系统盘就没了。我曾经有个同事,就是手滑把公司服务器的系统盘给镜像覆盖了……嗯,那场面,惨不忍睹。

如果磁盘很大,或者你想节省空间,可以用gzip配合dd实时压缩:

sudo dd if=/dev/sdb bs=4M status=progress | gzip -c > ./disk.img.gz

恢复的时候,反过来解压再写入:

gunzip -c ./disk.img.gz | sudo dd of=/dev/sdb bs=4M status=progress

还有一个我常用的技巧——稀疏镜像。如果磁盘大部分是空数据,用seek参数可以跳过空白区域,生成一个“看起来很大、实际很小”的镜像文件。不过这个操作有点复杂,咱们以后有机会再细讲。

4.3 处理坏道与读取错误

好了,最刺激的部分来了。你拿着dd去读一块坏盘,大概率会遇到读取错误。默认情况下,dd一遇到错误就停,然后你只能得到半个镜像。这显然不行。

我们需要告诉dd:遇到错误别停,跳过坏块继续读。用这两个参数:

sudo dd if=/dev/sdb of=./disk.img bs=4M conv=noerror,sync status=progress

conv=noerror,sync是关键:

  • noerror:遇到读取错误不停止,继续往下读。
  • sync:用空数据(通常是\0)填充因错误而缺失的块,保证镜像大小和原始盘完全一致。

但这里有个坑——bs设得太大,一个坏块就会导致4M数据全部变成空。设得太小,速度又慢。我一般这样权衡:

磁盘状态 建议块大小 原因
健康盘 4M - 8M 速度优先,块大吞吐高
少量坏道 64K - 512K 平衡速度与坏块损失
大量坏道 4K - 16K 宁可慢,也要尽量多抢救数据

注意:conv=noerror,sync只能保证镜像“完整”,但不能保证数据“正确”。坏块位置的数据已经被替换成了空字节。后续恢复时,你需要知道哪些块是坏的,哪些是好的。所以,我建议同时记录错误日志:

sudo dd if=/dev/sdb of=./disk.img bs=4K conv=noerror,sync status=progress 2>./dd_error.log

这个日志文件会记录所有读取失败的位置,方便你后续分析。

还有一个更高级的工具叫ddrescue(注意不是dd_rescue),它专门为坏盘镜像设计。它的工作方式是:先快速扫描好区域,再回头慢慢啃坏道区域。而且支持断点续传,镜像做到一半断电了也不怕。

# 先用ddrescue做第一遍快速扫描
sudo ddrescue -f -n /dev/sdb ./disk.img ./disk.log

# 再用慢速模式回头处理坏道
sudo ddrescue -d -r3 /dev/sdb ./disk.img ./disk.log

-f强制覆盖输出文件,-n跳过坏道扫描(快速),-d直接读取(绕过内核缓存),-r3重试3次。那个disk.log文件就是ddrescue的“地图”,记录哪些块已经读好、哪些块是坏的。

我曾在一次项目中,用ddrescue花了两天两夜,从一块有几千个坏道的2TB硬盘里,抢救出了98%的数据。客户拿到数据时,手都在抖。说实话,那种成就感,比写一万行代码都爽。

4.4 知识体系总览

下面这张图,把磁盘镜像的核心逻辑串起来了。你可以把它当作一个操作检查清单:

磁盘镜像制作核心流程 磁盘镜像制作核心流程 故障磁盘 /dev/sdb 选择镜像策略 健康盘:dd bs=4M 少量坏道:dd conv=noerror 大量坏道:ddrescue 镜像文件 disk.img 验证:哈希校验 + 错误日志分析 原始盘断电封存 镜像用于后续恢复

你看,整个流程其实不复杂。关键就是:先判断磁盘状态,再选择合适的工具和参数,最后一定要验证镜像的完整性。那个错误日志,千万别扔。它不仅能告诉你哪些数据可能丢了,还能帮你判断磁盘的损坏模式——是磁头问题还是盘面划伤?是固件故障还是逻辑坏道?这些信息,对后续的恢复策略至关重要。

好了,磁盘镜像这块就聊到这儿。记住一句话:镜像做得越扎实,恢复就越有把握。别嫌麻烦,别图省事。数据无价,谨慎为上。