主驱动器上的 dd 命令错误 - 如何恢复数据?

fri*_*mle 6 linux data-recovery partitioning dd

好吧,令人讨厌的愚蠢事情发生了。我想将 Arch Linux ISO 文件复制到我的 U 盘,但很匆忙,不小心将我的主驱动器作为of参数输入。

以下是详细信息:

$ sudo dd bs=4MB if=archlinux-2017.08.01-x86_64.iso of=/dev/nvme1n1
Run Code Online (Sandbox Code Playgroud)

/dev/nvme1n1应该是/dev/sdb

我的主驱动器/dev/nvme1n1包含两个分区:

  • 1 个 512 MB EFI 引导分区
  • 一个 ext4 分区跨越 1 TB 驱动器的其余部分

的文件大小archlinux-2017.08.01-x86_64.iso为 541065216 字节,或516 MB

计算机仍在运行并且似乎工作正常,并且我有运行命令之前lsblkdf -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
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

查看 的输出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
Run Code Online (Sandbox Code Playgroud)

我发现了几个相关的问题:

我已经安装了该testdisk实用程序,看起来很有希望,但我想确保在计算机仍在运行时执行正确的步骤。如果我现在关闭它,它将不再启动,所以这里是问题:

  • 从这种情况中恢复的最佳方法是什么?
  • 如何将分区表恢复到以前的形式,以及如何重新创建 /boot 分区?我正在使用最新的内核运行 Arch Linux。
  • 有什么方法可以知道我的根分区的前 4 MB 中包含(和销毁?)了什么?

编辑:根据@WumpusQ.Wumbley 对运行dumpe2fs命令的建议,在此处添加更多信息和详细信息。

基本输出(前 50 行)dumpe2fshttps : //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
Run Code Online (Sandbox Code Playgroud)

然后是很多组说[...]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
Run Code Online (Sandbox Code Playgroud)

整个文件系统中有很多备份超级块:

$ sudo dumpe2fs /dev/nvme1n1p2 | grep -i superblock | wc -l
dumpe2fs 1.43.5 (04-Aug-2017)
19
Run Code Online (Sandbox Code Playgroud)

小智 3

我假设分区表和启动分区可以很容易地重新创建,所以我将重点关注 ext4 分区。

文件系统的布局在某种程度上取决于创建它时使用的选项。我将描述常见情况。您可以通过在设备上运行来查看这是否与您的匹配dumpe2fs(这将有望在缓存中找到所有顶级元数据,而不是从磁盘读取)。

ext4 文件系统的正常块大小是 4096 字节,因此您丢失了 1024 个块。

第一个被覆盖的是块 0,即主要超级块。这本身不是问题,因为有备份超级块。之后是组描述符表,它也在文件系统内有备份。

然后是块位图和索引节点位图。这就是消息开始变得更糟的地方。如果其中任何一个低于块 1024(它们很可能是),那么您就丢失了有关正在使用哪些 inode 和块的信息。此信息是多余的,并且将由 fsck 根据它在遍历所有目录和 inode 时发现的内容(如果它们完好无损)进行重建。

但接下来是 inode 表,在这里你可能已经丢失了很多 inode,包括根目录、日志和其他特殊 inode。如果能把它们拿回来就好了。显然,根目录至少仍然有效,否则您尝试运行的几乎所有命令都将失败。

如果您dd if=/dev/nvme1n1p2 of=/some/external/device bs=4096 count=1024现在运行,您将获得当前缓存中所有内容的备份副本,其中包含未缓存块的错误数据。然后,在启动救援磁盘后,您可以dd反向执行相同的操作,将部分良好的数据放回到磁盘上,覆盖现在存在的所有坏数据。

之后,您可能会发现自动恢复工具 ( fscktestdisk) 工作得足够好。如果没有,您可以使用地图来帮助手动恢复。使用 中的“空闲块”列表dumpe2fs,您知道要忽略哪些块。

您丢失的大部分内容可能是索引节点。实际上很可能磁盘的前 4MB 中没有文件内容。(我mkfs.ext4在 1TB 图像文件上没有任何选项地运行,第一个非元数据块结果是块 9249)

您设法恢复的每个索引节点都将识别整个文件的数据块。这些数据块可能位于整个磁盘上,不一定位于附近。

第二天

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
Run Code Online (Sandbox Code Playgroud)

由于我们认为文件系统开头只有 4MB 被覆盖,因此我们只需要担心块 0-1023。保留的 GDT 块一直到块 1141!这种损坏应该通过简单的修复e2fsck -b $backup_superblock_number(重新启动后)。你至少可以尝试一下,-n看看它是怎么想的。