好吧,一件令人恼火的蠢事发生了。我想将 Arch Linux ISO 文件复制到我的 USB 拇指驱动器,但当时太着急,不小心输入了我的主驱动器作为参数of
。
以下是详细信息:
$ sudo dd bs=4MB if=archlinux-2017.08.01-x86_64.iso of=/dev/nvme1n1
/dev/nvme1n1
本来应该/dev/sdb
。
我的主驱动器/dev/nvme1n1
包含两个分区:
- 一个 512 MB EFI 启动分区
- 一个 ext4 分区跨越 1 TB 驱动器的剩余部分
文件大小为archlinux-2017.08.01-x86_64.iso
541065216 字节,或516 兆
计算机仍在运行,似乎工作正常,并且我得到了输出lsblk
和df -h
前运行该dd
命令。输出为一模一样就像我现在运行命令时一样。我假设是因为数据被缓存了:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:5 0 931.5G 0 disk
├─nvme1n1p1 259:6 0 512M 0 part /boot
└─nvme1n1p2 259:7 0 931G 0 part /
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/nvme1n1p2 916G 22G 848G 3% /
/dev/nvme1n1p1 511M 36M 476M 7% /boot
ls /boot
仍然打印目录内容(可能是缓存的信息),但文件内容已损坏,并且正在运行ls /boot/EFI
,或者ls /boot/loader
用随机字符填满屏幕,包括大量的Input/output error
。
以下是更多信息:
$ cat /proc/partitions
major minor #blocks name
259 5 976762584 nvme1n1
259 6 524288 nvme1n1p1
259 7 976237255 nvme1n1p2
$ sudo fdisk -l /dev/nvme1n1
Disk /dev/nvme1n1: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
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: 0x282bad86
Device Boot Start End Sectors Size Id Type
/dev/nvme1n1p1 * 0 1056767 1056768 516M 0 Empty
/dev/nvme1n1p2 164 131235 131072 64M ef EFI (FAT-12/16/32)
查看 的输出fdisk
,很明显分区表(可能还有启动分区上的所有数据)被破坏了。它应该是gpt
磁盘标签类型,分区大小/类型错误。不幸的是,由于 ISO 文件大小(516 MB),它也覆盖了我的根分区的前 4 MB。
输出与以下稍有不同gdisk
:
$ sudo gdisk /dev/nvme1n1
# selected GPT when asked "Found valid MBR and GPT. Which do you want to use?"
Command (? for help): p
Disk /dev/nvme1n1: 1953525168 sectors, 931.5 GiB
Model: Samsung SSD 960 EVO 1TB
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): <guid>
Partition table holds up to 248 entries
Main partition table begins at sector 2 and ends at sector 63
First usable sector is 64, last usable sector is 1056704
Partitions will be aligned on 8-sector boundaries
Total free space is 1 sectors (512 bytes)
Number Start (sector) End (sector) Size Code Name
2 164 131235 64.0 MiB 0700 ISOHybrid1
我发现了几个相关问题:
- https://askubuntu.com/questions/94421/is-there-a-way-to-recover-files-from-a-storage-device-partially-overwritten-with
- 意外用 dd 覆盖了错误的磁盘,如何恢复?
我已经安装了该testdisk
实用程序,它看起来很有希望,但我想确保我执行了正确的步骤当计算机仍在运行时。如果我现在关闭它,它将无法再启动,因此存在以下问题:
- 摆脱这种情况的最佳方法是什么?
- 如何将分区表恢复到以前的格式,以及如何重新创建 /boot 分区?我正在运行带有最新内核的 Arch Linux。
- 有什么方法可以知道我的根分区的前 4 MB 包含什么(以及销毁了什么)?
编辑:根据@WumpusQ.Wumbley 运行dumpe2fs
命令的建议,在此添加更多信息和详细信息。
基本输出(前 50 行)dumpe2fs
:https://pastebin.com/fBuFRQfE
对我来说它看起来很正常,甚至文件系统魔法数字(0xEF53
)也是正确的。
接下来是Group 0
:
Group 0: (Blocks 0-32767) csum 0x9569 [ITABLE_ZEROED]
Primary superblock at 0, Group descriptors at 1-117
Reserved GDT blocks at 118-1141
Block bitmap at 1142 (+1142)
Inode bitmap at 1158 (+1158)
Inode table at 1174-1685 (+1174)
21349 free blocks, 8177 free inodes, 2 directories, 8177 unused inodes
Free blocks: 11419-32767
Free inodes: 16-8192
随后有很多组表示,[...]8192 free inodes, 0 directories, 8192 unused inodes [...]
第一个真正报告一些目录的组直到Group 3648
,或者大约 25,000 行之后才:
Group 3648: (Blocks 119537664-119570431) csum 0xa9ea [ITABLE_ZEROED]
Block bitmap at 119537664 (+0)
Inode bitmap at 119537680 (+16)
Inode table at 119537696-119538207 (+32)
23930 free blocks, 1670 free inodes, 614 directories, 1670 unused inodes
Free blocks: 119546502-119570431
Free inodes: 29890939-29892608
整个文件系统有很多备份超级块:
$ sudo dumpe2fs /dev/nvme1n1p2 | grep -i superblock | wc -l
dumpe2fs 1.43.5 (04-Aug-2017)
19
答案1
我假设分区表和启动分区可以轻松地重新创建,所以我将重点关注 ext4 分区。
文件系统的布局在某种程度上取决于创建时使用的选项。我将描述常见情况。您可以通过dumpe2fs
在设备上运行来查看这是否与您的情况相匹配(希望在缓存中找到所有顶级元数据,而不是从磁盘读取)。
ext4 文件系统的正常块大小为 4096 字节,因此您丢失了 1024 个块。
首先被覆盖的是块 0,即主超级块。这本身不是问题,因为还有备份超级块。之后是组描述符表,它在文件系统中也有备份。
然后是块位图和 inode 位图。这是消息开始变得稍微糟糕的地方。如果其中任何一个低于块 1024(很可能是这样),您就丢失了有关正在使用哪些 inode 和块的信息。这些信息是多余的,如果所有目录和 inode 都完好无损,fsck 将根据遍历所有目录和 inode 时发现的内容重建这些信息。
但接下来是 inode 表,在这里你可能丢失了很多 inode,包括根目录、日志和其他特殊 inode。如果能找回这些就好了。显然,至少根目录仍然可用,否则你尝试运行的所有命令都会失败。
如果您现在运行dd if=/dev/nvme1n1p2 of=/some/external/device bs=4096 count=1024
,您将获得当前缓存中所有内容的备份副本,其中混合了未缓存块的坏数据。然后,在启动救援磁盘后,您可以dd
反向执行相同操作,将部分好的数据放回磁盘上,覆盖现在所有坏的数据。
在此之后,您可能会发现自动恢复工具(fsck
、testdisk
)工作得很好。如果不是,您可以使用一张地图来帮助手动恢复。使用 中的“空闲块”列表dumpe2fs
,您知道要忽略哪些块。
你丢失的大部分内容可能是 inode。实际上,你很可能没有文件内容在磁盘的前 4MB 中。(我mkfs.ext4
在 1TB 图像文件上运行了无任何选项,第一个非元数据块竟然是块 9249)
您设法恢复的每个 inode 都将标识整个文件的数据块。这些数据块可能位于磁盘的各处,而不一定位于附近。
第 2 天
pastebin 上发布的转储揭示了好消息:
Group 0: (Blocks 0-32767) csum 0x9569 [ITABLE_ZEROED]
Primary superblock at 0, Group descriptors at 1-117
Reserved GDT blocks at 118-1141
Block bitmap at 1142 (+1142)
Inode bitmap at 1158 (+1158)
Inode table at 1174-1685 (+1174)
21349 free blocks, 8177 free inodes, 2 directories, 8177 unused inodes
Free blocks: 11419-32767
Free inodes: 16-8192
由于我们认为文件系统开头的 4MB 被覆盖了,所以我们只需要担心 0-1023 块。而保留的 GDT 块一直延伸到 1141 块!这种损坏应该可以通过简单的方法e2fsck -b $backup_superblock_number
(重启后)进行修复。您至少可以尝试一下,-n
看看它是怎么想的。
答案2
如果磁盘使用 GPT,则可以使用磁盘末尾的备份 GPT 数据恢复分区表。您可以使用 执行此操作gdisk
;请参阅gdisk
数据恢复文档了解详情。简而言之:当您gdisk
在磁盘上启动时,它将大概注意到损坏并询问您是否要使用备份 GPT 数据或 MBR 数据。如果您选择 GPT 选项然后写入更改,分区表将被修复。如果gdisk
没有询问要使用哪个分区表,您可能仍然可以使用恢复和转换菜单上的选项加载备份表c
。
/sys/block/nvme1n1/nvme1n1p1/start
如果失败,您仍然可以使用和/sys/block/nvme1n1/nvme1n1p1/size
文件中的数据(以及 中的数据)重新创建分区表(或至少是分区的起点和终点)/dev/nvme1n1p2
。但是,如果您求助于这些数据,则必须不是关闭计算机,这与 hek2mgl 的建议相反。话虽如此,hek2mgl 认为继续使用当前状态的磁盘可能会使情况变得更糟,这一点并没有错。总的来说,我认为最好的折衷方案是尽快修复分区表问题,然后关闭计算机并从紧急磁盘修复文件系统问题。
不幸的是,您的 ESP 已损坏。考虑到您的磁盘布局,我猜您将 ESP 安装在了/boot
并将内核存储在那里。因此,您需要使用chroot
或其他方式重新安装内核包。您的引导加载程序或引导管理器也是如此。
答案3
- 立即关闭计算机
- 使用救援系统启动它。
- 运行
testdisk
以尝试恢复您的数据。(如果您有足够的空间,请使用该设备获取图像并在该图像上dd
运行)testdisk
为什么要立即关闭计算机?如果要创建新文件(可能在 /run 中)或将新文件附加到(/var/log/...),则文件系统需要查看现有(错误!)信息以决定将数据存储在何处。当根据错误信息做出此决定时,现有数据块被覆盖的风险很高。这会使它们永远丢失。即使对于像testdisk
和 这样的工具也是如此photorec
。