黑客与 / - 当灾难来袭:硬盘崩溃

作者:Kyle Rankin

以下是关于 Linux 灾难以及如何从中恢复的系列专栏的开篇,部分灵感来源于万圣节 Linux Journal 直播节目“恐怖故事”。您可以在 www.linuxjournal.com/video/linux-journal-live-horror-stories 观看原始节目。

没有什么比一次好的灾难更能教会你关于 Linux 的知识了。无论是硬盘崩溃,误操作的rm -rf命令还是 fdisk 错误,作为 Linux 用户,你的普通一天可能会变成噩梦,方法有很多。现在,随着噩梦而来的是巨大的机会:我通过意外地破坏 Linux 然后不得不修复它,学到的关于 Linux 如何工作的知识,比我在一切顺利运行时学到的还要多。请相信我,以下关于系统恢复的文章系列是来之不易的知识。

如果维护良好,计算机设备非常可靠。尽管多年来我经历过几乎所有主要计算机部件的故障,但事实是,我拥有的计算机超出其使用寿命的次数多于没有超出其使用寿命的次数。即便如此,有一种计算机组件你几乎可以肯定会在某个时候发生故障——硬盘驱动器。你可以将其归咎于快速移动的部件、计算机系统内部的振动和热量,甚至是工厂叉车上的错误,但是当你的硬盘驱动器过早发生故障时,五年的保修期也无法让你对所有你忘记备份的丢失数据感觉好一点。

你可以做的最重要的事情来保护自己免受硬盘崩溃(或实际上大多数 Linux 灾难)的影响是备份你的数据。备份你的数据!即使是好的 RAID 系统也无法保护你免受所有硬盘故障的影响(此外,如果你意外删除文件,RAID 也无法保护你),因此如果数据很重要,请务必备份它。测试你的备份与首先进行备份同样重要。如果你没有测试恢复备份,那么你就没有真正备份任何东西。我下面列出的从崩溃的硬盘恢复数据的方法比从备份恢复数据要耗时得多,因此如果可能的话,请备份你的数据。

现在我已经讲完课了,让我们假设由于某种原因,你的一个硬盘驱动器崩溃了,而你没有备份。并非一切都必然丢失。硬盘驱动器故障有很多不同的类型。现在,在真正的硬盘驱动器崩溃中,硬盘驱动器的磁头实际上会撞到以高速旋转的盘片上。我见过磁头碰撞后的盘片,在某些部分是半透明的,因为磁头刮掉了所有的磁性涂层。如果这种情况发生在你身上,我在这里列出的任何命令都帮不了你。你唯一的求助对象将是专门从事硬盘恢复的取证公司之一。当大多数人说他们的硬盘驱动器崩溃时,他们说的是不太极端的故障。通常,发生的情况是硬盘驱动器已经出现了很多坏块——多到你无法挂载文件系统——或者在其他情况下,存在一些不同的故障,导致当你尝试从硬盘驱动器读取数据时出现 I/O 错误。在许多这些情况下,你可以恢复至少一部分,如果不是大部分数据。我曾成功地从发出可怕声音并且其他人完全放弃的驱动器中恢复数据,而且只需要几个命令和一点耐心。

创建恢复镜像

硬盘恢复工作的前提假设是驱动器上的并非所有数据都是坏的。一般来说,如果你的硬盘驱动器上有坏块,它们通常会聚集在一起。如果你可以访问驱动器上的其余数据,那么这些数据可能仍然完好无损。当硬盘驱动器开始坏死时,它们通常会分阶段进行,因此你希望尽可能快地恢复尽可能多的数据。如果硬盘驱动器有 I/O 错误,如果你在设备本身上运行文件系统检查或其他修复,有时可能会进一步损坏数据。相反,你想做的是创建驱动器的完整镜像,存储在良好的介质上,然后使用该镜像进行操作。

有很多镜像工具可用于 Linux——从经典的 dd 程序到高级 GUI 工具——但它们中的大多数的问题在于,它们被设计用于对健康的驱动器进行镜像。不健康驱动器的问题是,当你尝试从坏块读取数据时,你会收到 I/O 错误,并且大多数标准镜像工具在遇到错误时都会以某种方式失败。虽然你可以告诉 dd 忽略错误,但它会愉快地跳到下一个块,并且对于它无法读取的块不写入任何内容,因此你最终可能会得到一个小于你的驱动器的镜像。当你对不健康的驱动器进行镜像时,你需要一个专为此工作设计的工具。对于 Linux,该工具是 ddrescue。

ddrescue 或 dd_rescue

为了使事情有点混乱,有两个名称几乎相同的类似工具。dd_rescue(带下划线)是一个较旧的救援工具,仍然可以完成工作,但它的工作方式相当基本。它从驱动器的开头开始,当遇到错误时,它会重试多次,然后移动到下一个块。最终(通常在几天后),它到达驱动器的末尾。通常坏块聚集在一起,并且在所有坏块都靠近驱动器开头的情况下,你可能会浪费大量时间尝试读取它们,而不是恢复所有好块。

ddrescue 工具(不带下划线)是 GNU 项目的一部分,它进一步扩展了 dd_rescue 的基本算法。ddrescue 尝试首先从设备中恢复所有好数据,然后划分并征服剩余的坏块,直到它尝试恢复整个驱动器。ddrescue 的另一个附加功能是它可以选择维护一个它已经恢复的内容的日志文件,因此你可以停止程序,然后在你离开的地方恢复。当您认为 ddrescue 已经恢复了大部分好数据时,这很有用。您可以停止程序并制作大部分完整镜像的副本,以便您可以尝试修复它,然后再次启动 ddrescue 以完成镜像。

准备镜像

创建失败驱动器的镜像时,您需要做的第一件事是另一个大小相等或更大的驱动器来存储镜像。如果您计划将第二个驱动器用作替换驱动器,您可能希望直接从一个设备镜像到下一个设备。但是,如果您只想挂载镜像并恢复特定文件,或者想将镜像存储在已格式化的分区上,或者想从另一台计算机恢复,您很可能会将镜像创建为文件。如果您确实想镜像到文件,如果您一次从驱动器镜像一个分区,您的工作将更简单。这样,稍后挂载和 fsck 镜像会更容易。

ddrescue 程序可以作为软件包提供(Debian 和 Ubuntu 中的 ddrescue),或者您可以从项目页面下载并安装它。请注意,如果您尝试恢复系统的主磁盘,您显然需要使用第二台系统进行恢复,或者找到一个带有 ddrescue 或可以实时安装它的救援盘(例如,Knoppix 符合要求)。

运行 ddrescue

一旦安装了 ddrescue,运行它就相对简单了。第一个参数是你要镜像的设备。第二个参数是你要镜像到的设备或文件。可选的第三个参数是 ddrescue 可以维护以便它可以恢复的日志文件的路径。对于我们的示例,假设我有一个故障硬盘驱动器位于 /dev/sda,并且已挂载一个大分区以将镜像存储在 /mnt/recovery/。我将运行以下命令来救援 /dev/sda 上的第一个分区

$ sudo ddrescue /dev/sda1 /mnt/recovery/sda1_image.img
/mnt/recovery/logfile
Press Ctrl-C to interrupt
Initial status (read from logfile)
rescued:        0 B,  errsize:   0 B,  errors:       0
Current status
rescued:  349372 kB,  errsize:   0 B,  current rate: 19398 kB/s
   ipos:  349372 kB,   errors:   0,    average rate: 16162 kB/s
   opos:  349372 kB

请注意,您需要以 root 权限运行 ddrescue。另请注意,我指定了 /dev/sda1 作为源设备,因为我想镜像到文件。如果我要输出到另一个硬盘驱动器设备(如 /dev/sdb),我将指定 /dev/sda 代替。如果此驱动器上有多个分区要恢复,我将为每个分区重复此命令,并将每个分区保存为其自己的镜像。

正如你所看到的,ddrescue 的一个优点是它不断地给你更新输出,因此你可以衡量你救援分区的进度。事实上,在某些情况下,我更喜欢使用 ddrescue 而不是 dd 进行常规镜像,只是为了进度输出。当考虑到救援故障驱动器可能需要多长时间时,拥有持续的进度输出也很有用。在某些情况下,甚至可能需要几天时间,具体取决于驱动器的大小,因此了解你进展到什么程度是很好的。

修复镜像文件系统

一旦你有了你的驱动器或分区的完整镜像,下一步就是修复文件系统。据推测,存在坏块和 ddrescue 无法恢复的区域,因此这里的目标是尝试修复足够的文件系统,以便你至少可以挂载它。现在,如果你已镜像到另一个硬盘驱动器,你将针对驱动器上的各个分区运行 fsck。在我的情况下,我创建了一个镜像文件,因此我可以直接针对该文件运行 fsck

$ sudo fsck -y /mnt/recovery/sda1_image.img

我假设我会在文件系统上遇到错误,所以我添加了 -y 选项,这将使 fsck 继续并尝试修复所有错误,而无需提示我。

挂载镜像

一旦 fsck 完成,我可以尝试挂载文件系统并恢复我的重要文件。如果你镜像到整个硬盘驱动器并想尝试从中启动,在你 fsck 每个分区后,你将尝试单独挂载它们,看看你是否可以从中读取数据,然后将驱动器交换到你的原始计算机中并尝试从中启动。在我的示例中,我只想尝试从此镜像中恢复一些重要文件,因此我将环回挂载镜像文件

$ sudo mount -o loop /mnt/recovery/sda1_image.img /mnt/image

现在我可以浏览 /mnt/image 并希望我的重要文件不在损坏的块中。

最后的手段

不幸的是,在某些情况下,硬盘驱动器有太多错误,fsck 无法纠正。在这些情况下,你甚至可能无法挂载文件系统。如果发生这种情况,你不一定完全倒霉。根据你要恢复的文件类型,你或许能够直接从镜像中提取你需要的信息。例如,如果你有一篇关键的学期论文或其他你需要从机器上检索的文档,只需在镜像上运行 strings 命令并输出到第二个文件

$ sudo strings /mnt/recovery/sda1_image.img >
/mnt/recovery/sda1_strings.txt

sda1_strings.txt 文件将包含镜像中的所有文本(这可能会变成大量数据),从手册页条目到配置文件再到程序二进制文件中的输出。有很多数据需要筛选,但是如果你知道你的学期论文中的关键词,你可以在less中打开此文本文件,然后按 / 键并键入你的关键词以查看是否可以找到它。或者,你可以通过 strings 文件 grep 你的关键词和周围的行。例如,如果你正在撰写关于海豚的学期论文,你可以运行

$ sudo grep -C 1000 dolphin /mnt/recovery/sda1_strings.txt >
/mnt/recovery/dolphin_paper.txt

这不仅会拉出包含单词 dolphin 的任何行,还会拉出周围的 1,000 行。然后,你可以浏览 dolphin_paper.txt 文件并删除不属于你的论文的行。你可能需要调整 grep 中的 -C 参数,以便它捕获更多行。

总之,当你的硬盘驱动器开始发出奇怪的声音并且无法挂载时,这不一定是世界末日。虽然 ddrescue 不能替代良好、经过测试的备份,但当灾难袭击你的硬盘驱动器时,它仍然可以拯救你。另请注意,ddrescue 几乎可以在任何设备上工作,因此你也可以使用它来尝试恢复那些划伤的 CD-ROM 光盘。

Kyle Rankin 是旧金山湾区的高级系统管理员,也是包括 O'Reilly Media 的 Knoppix HacksUbuntu Hacks 在内的多本书籍的作者。他目前是北湾 Linux 用户组的主席。

加载 Disqus 评论