总结:
- 我把装有 SSD 的笔记本电脑掉在地上
- 该驱动器不再可安装或无法进行 fsck(可怕的输入/输出错误)
- 但是,磁盘仍然完好无损/可以正常工作,可以读取分区表并检查加密密码
- 如果通过 USB 外部连接,驱动器将完全不可见,根本无法识别
- 发生了什么?
- 有什么办法可以解决这个问题吗?
详细信息:
我有一台 2012 年的旧 ThinkPad T420。我运行的是 Ubuntu 20.04,主分区已加密。几天前我把它摔了。它立即关机,并且无法再启动到主驱动器。
主启动驱动器是 SSD(三星 870 EVO),它通过托架连接到笔记本电脑,该托架可使驱动器适应光驱托架。
虽然 SSD 或适配器没有明显损坏,但我的第一个想法是损坏的是连接器/适配器,或者类似的东西已经损坏或松动。因此,我从笔记本电脑中取出 SSD,并将其连接到SATA 到 USB 适配器。这完全失败了。我将其插入几台不同的计算机,驱动器似乎完全不可见(没有新设备/dev
,没有条目lsusb
)。(当我用不同的硬盘测试它时,SATA 到 USB 适配器本身工作正常。)
但是,如果我将 SSD 放回其原始位置/托盘并通过 USB 启动到 Linux,则驱动器并非完全不可见,但似乎也无法实际使用。
我可以看到该驱动器的分区表:
ubuntu@ubuntu:~$ sudo fdisk -l /dev/sda
Disk /dev/sda: 465.76 GiB, 500107862016 bytes, 976773168 sectors
Disk model: Samsung SSD 870
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: 0xe62c1c13
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32
/dev/sda2 1052670 976771071 975718402 465.3G 5 Extended
/dev/sda5 1052672 2549759 1497088 731M 83 Linux
/dev/sda6 2551808 976771071 974219264 464.5G 83 Linux
该驱动器已加密,因此我不能直接安装它,而是需要先经过一些繁琐的程序:
ubuntu@ubuntu:~$ sudo cryptsetup open /dev/sda6 ssd
Enter passphrase for /dev/sda6:
如果我输入了错误的密码,它会拒绝我:
Warning: keyslot operation could fail as it requires more than available memory.
No key available with this passphrase.
但如果我输入正确的密码,它就会让我进入,并且设备/dev/mapper/ssd
也会按预期出现。
现在还有一步繁琐的程序。命令是sudo vgchange -ay
,它应该会导致设备/dev/vgubuntu/root
出现。当我第一次尝试时,这个命令有效,但目前,它不再起作用(随着时间的推移,情况越来越糟,见下文)。
此时,您应该能够挂载/dev/vgubuntu/root
,但mount
会因一般的“输入/输出错误”而失败(目前没有确切的错误)。fsck
还会因“输入/输出错误”和第二个错误(例如“未找到超级块”)而失败。
目前我正在运行ddrescue
以查看可以恢复什么:
sudo ddrescue --idirect /dev/sda /media/ubuntu/whatever/rescue.img /media/ubuntu/whatever/rescue.log
它确实似乎在做一些事情,但是进展非常缓慢而且我有点怀疑它是否真的会成功。
另外需要注意的是:驱动器插入的时间越长,问题似乎就越严重,错误也越多。例如,最初你可以使用sudo fdisk -l /dev/sda
上面所示的命令读取分区表。但是,最终它将停止工作:
ubuntu@ubuntu:~$ sudo fdisk -l /dev/sda
fdisk: cannot open /dev/sda: Invalid argument
但是,如果您弹出驱动器并再次放回去,它将再次开始工作。
磁盘出了什么问题?有什么办法可以恢复它吗?
关于第一个问题:
我确实不知道,但可以参阅 DrMoishe Pippik 和 Ramhound 的评论以获得部分解释。
对于第二个问题:
答案是肯定的。无论问题是什么,磁盘损坏得都不是太严重;
ddrescue
能够从磁盘恢复几乎所有信息,并且能够提取我需要的所有文件。我将介绍整个恢复过程,希望它能够帮助到其他人。
正如我之前提到的,我必须内部连接驱动器而不是通过 USB 才能读取它,所以这就是我在这里所做的:通过 USB 启动到实时 Linux,读取计算机内部损坏的驱动器,然后复制到通过 USB 连接的备份驱动器。
第一步是运行,它基本上就是按照广告宣传的那样运行。我使用了此处的
ddrescue
指南,但有一个重要的警告:如果您使用的是实时 Linux,请不要像我一样愚蠢,将救援日志保存在主目录中,该日志会在您重新启动后立即消失。因此,最初要运行的命令是
我看到的最终输出是
99.98% 的人第一次尝试就获救,还不错。
(附注:有时,
ddrescue
会失败并显示消息ddrescue: /dev/sdc: Unaligned read error. Is sector size correct?
。发生这种情况时,弹出磁盘然后将其弹回,并重新运行完全相同的命令(但要确保设备名称没有更改,例如从/dev/sdc
更改为/dev/sdd
),它将从上次中断的地方继续。)初次运行后,您可以尝试重试,重试使用完全相同的命令,只是
--retry-passes=N
添加了参数。我的经验是,每次额外的重试都会挽救几百 kB 的数据,但对于如此少量的数据来说,速度太慢了,以至于我一度放弃了。现在,您的磁盘映像中有几个(约 10,000 个)漏洞。如果您愿意,可以复制一份映像,以防您弄砸了第一个。
此时我能够挂载感兴趣的文件系统:
此时,我可以看到完整的目录结构和所有文件。我打开了几个文件,一切似乎都很正常。
在做其他事情之前,我想确定哪些文件会被损坏(即哪些文件的坏扇区中存储了无法通过 ddrescue 恢复的数据)。有一个工具
ddrutility
应该可以做到这一点,但它似乎不起作用,我怀疑它不适用于加密磁盘。所以我写了几个非常快速和粗糙的 python 脚本来完成这项工作。(感谢这个答案告诉我debugfs
要运行的命令)请注意,在下面的脚本中,值必须
partition_start_sectors
正确!如果您有一个简单的分区方案,则只需使用它fdisk -l
来找到它。但是,对于使用 LUKS 和 LVM 的设置,这还不够。最后,我找到了命令dmsetup table
,它显示了所需的信息:因此相关偏移量是 2551808 + 32768 + 2048。
脚本 1 在恢复日志中查找与坏扇区相关的文件系统块号和 inode:
脚本2查找与inode关联的文件名:
这确定了大约 250 个已损坏的文件。果然,当我尝试打开这些假定已损坏的文件时,它们会变得一团糟(例如,jpeg 图像部分呈现,mp3 图像出现咔嗒声和跳过)。幸运的是,在这 250 个文件中,它们要么是我不在乎的文件,要么是我已经有足够的先前备份的文件。
它还识别出大约 200 个未恢复的文件系统块,这些块与任何文件均无关联。我不太确定该如何处理这些块。查看 的输出
dumpe2fs
,似乎这些块不包含文件系统元数据。但它们也没有被标记为空闲。所以不确定它们到底是什么。此后,您可以运行
fsck
。尽管出于某种原因,我不明白fsck
命令本身没有执行任何操作,所以我需要运行e2fsck
:fsck
会发现很多错误,但幸运的是,对我来说没有什么灾难性的。此时,您可以安装驱动器并从中复制所需的所有文件。