![使用部分映像及其扇区列表重建大量碎片文件](https://linux22.com/image/1545954/%E4%BD%BF%E7%94%A8%E9%83%A8%E5%88%86%E6%98%A0%E5%83%8F%E5%8F%8A%E5%85%B6%E6%89%87%E5%8C%BA%E5%88%97%E8%A1%A8%E9%87%8D%E5%BB%BA%E5%A4%A7%E9%87%8F%E7%A2%8E%E7%89%87%E6%96%87%E4%BB%B6.png)
为了从故障的 3TB HDD 中恢复尽可能多的数据,我进行了如下操作:
- 我使用 HD Sentinel 进行了表面扫描,发现了两个小的受损区域和大约 100 个坏扇区(之前数量为 16 个)。
- 然后我确定了哪些文件受到坏扇区的影响使用各种方法。
- 我将这些文件(六个大型视频文件)移动到一个特殊文件夹中,并按重要性降序复制了其余文件和文件夹;除了一个不重要的 .eml 文件(恰好位于已识别的坏扇区附近)外,所有内容均成功复制。
- 然后,我认为从剩余文件(不再在线且我没有备份的电视广播)中获取最大收益的最安全方法是使用 ddrescue – 但由于我唯一的空硬盘是 500GB,我无法对所有内容进行映像处理。其中一些文件碎片很多(每个文件有 6000 到 12000 个碎片 – 它们是同时下载的,我猜这就是为什么它们以“交错”模式写入导致这种程度的碎片,因为否则硬盘会有足够的可用空间),所以我无法通过提取它们占用的扇区来恢复它们,但我认为通过对前 10GB 进行映像处理,通常包含整个 MFT 和所有其他系统文件,以及这些文件所在的四个区域,我可以使用 WinHex 或 R-Studio 轻松地从映像中提取它们。
但不幸的是,我没有得到整个 MFT:其中的一部分(我后来检查了我之前创建的分区的完整 nfi.exe 列表时发现)位于 200GB 标记附近,第三个块位于分区的最末端,接近 3TB 标记。我没想到 HDD 的状态会在恢复尝试期间恶化得如此之快(现在它有超过 12000 个重新分配的扇区和 9000 个待处理的扇区,仅仅几个小时后!...),而且我没有采取预防措施从 WinHex 保存 MFT。现在,使用 ddrescue 已经变得非常慢,我可能无法获得整个 MFT。另外,如果我用 WinHex 打开该部分映像,它会使用我在检查物理设备时创建的相同卷快照,我想要的文件会以其正确的大小和日期列出,如果我单击它们,它会显示正确的第一个扇区,但它仍然无法提取它们(仅提取了 0 字节文件),显然卷快照不包含有关分配扇区的所有必需数据,WinHex 似乎依赖于 MFT,所以这也不起作用。
但我已经恢复了包含这六个文件的大部分数据块,并且我为每个文件都提供了它们所占扇区/簇的详细列表(使用三种不同的工具获得:nfi.exe、Recuva、HD Sentinel)。现在,我如何使用自动脚本利用这些信息重建这些文件?(手动完成这项工作是不可能的。)
使用 ddrescue 我可以使用 -i(输入位置)-o(输出位置)和 -s(输入大小)开关,但如何才能自动化该过程并同时运行数千条命令?
在 Windows 上,我知道一个名为德斯福可以使用以下命令将数据从任何源提取到目标文件:
dsfo [source] [offset] [size] [destination]
我可以使用 Calc 和 TEDNotepad 的组合来编辑扇区/群集列表,以创建 dsfo 命令列表,但这会创建数千个块,然后我必须以某种方式将它们连接起来。有没有更好的方法可以一步完成此操作?
编辑 :
因此我获取了由 HD Sentinel 生成的其中一个文件的簇/扇区列表,其呈现方式如下:
R:\fichiers corrompus\2017_07_2223_58 - Arte - Pink Floyd - The Dark Side of the Moon Live.mp4
Total Size: 883 787 365 bytes Position: 0 Attributes: Arc
Number of file fragments: 6040
VCN: 0 LCN: 516530293 Length: 4288 sectors: 4132506536 - 4132540839
VCN: 4288 LCN: 516534613 Length: 16 sectors: 4132541096 - 4132541223
VCN: 4304 LCN: 516534645 Length: 64 sectors: 4132541352 - 4132541863
VCN: 4368 LCN: 516534725 Length: 16 sectors: 4132541992 - 4132542119
VCN: 4384 LCN: 516534757 Length: 48 sectors: 4132542248 - 4132542631
VCN: 4432 LCN: 516534853 Length: 32 sectors: 4132543016 - 4132543271
VCN: 4464 LCN: 516534901 Length: 16 sectors: 4132543400 - 4132543527
VCN: 4480 LCN: 516534933 Length: 48 sectors: 4132543656 - 4132544039
VCN: 4528 LCN: 516535013 Length: 16 sectors: 4132544296 - 4132544423
...
VCN: 215760 LCN: 568126709 Length: 9 sectors: 4545277864 - 4545277935
第一个字段可能代表“虚拟簇号”(在集成帮助中没有找到详细描述),无论如何,这个值显然代表相对于文件开头的簇号。第二个值必须是“逻辑簇号”,是相对于分区开头的簇号(见下文,我一开始搞错了,以为这个值是相对于整个设备的)。第三个值代表每个片段的长度,也是以簇为单位。这三个值应该足以满足我的意图和目的。
我将其导入 TED 记事本,然后使用“工具”>“行”>“列,数字”功能,选择第 2、3、1 列并使用制表符作为分隔符,得到以下输出:
LCN: 516530293 Length: 4288 VCN: 0
LCN: 516534613 Length: 16 VCN: 4288
LCN: 516534645 Length: 64 VCN: 4304
LCN: 516534725 Length: 16 VCN: 4368
LCN: 516534757 Length: 48 VCN: 4384
LCN: 516534853 Length: 32 VCN: 4432
LCN: 516534901 Length: 16 VCN: 4464
LCN: 516534933 Length: 48 VCN: 4480
LCN: 516535013 Length: 16 VCN: 4528
...
LCN: 568126709 Length: 9 VCN: 215760
然后我将其导入 Calc,使用制表符和空格作为分隔符,添加一列以计算来自簇号的输入偏移量(=LCN*8*512),另一列用于根据簇长度计算字节长度(=Length*8*512),最后添加另一列以从 VCN 值获取输出偏移量(=VCN*8*512),将公式粘贴到所有其他行,删除多余的列,将“LCN:”替换为“ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i”,将“Length:”替换为“-s”,将“VCN:”替换为“-o”......
现在我得到了这个(除了每个文件有 6000-12000 行):
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115708080128 -s 17563648 -o 0
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115725774848 -s 65536 -o 17563648
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115725905920 -s 262144 -o 17629184
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115726233600 -s 65536 -o 17891328
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115726364672 -s 196608 -o 17956864
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115726757888 -s 131072 -o 18153472
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115726954496 -s 65536 -o 18284544
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115727085568 -s 196608 -o 18350080
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2115727413248 -s 65536 -o 18546688
...
ddrescue /media/sdb1/ST3000DM001-2.dd /media/sdb1/201707222358.mp4 -i 2327047000064 -s 36864 -o 883752960
那么,在 Knoppix 实时系统上运行这一大系列命令的最简单方法是什么?Linux 中与 Windows 命令提示符的批处理脚本等效的是什么?
(我可以在 P2P 网络上找到该特定文件,因此我可以测试此方法是否有效,如果有效,则评估损坏程度。其他五个文件就没有那么幸运了。其中一个文件没有碎片,因此我可以将其作为一个数据块提取:末尾附近有许多空白扇区,但其余部分是可读的。因此,剩下四个文件可以通过这种方式提取。)
答案1
所以我确实运行了那些 ddrescue 脚本(首先使用“chmod +x”命令使它们可执行,然后使用 ./name_of_the_script 调用它们):
– 起初命令不起作用,ddrescue 只给出错误,我不得不再次编辑脚本,以便将参数放在输入和输出文件的名称之前。命令如下所示:
ddrescue -P -i 2115843346432 -s 17563648 -o 0 ST3000DM001-2.dd 201707222358.mp4
ddrescue -P -i 2115861041152 -s 65536 -o 17563648 ST3000DM001-2.dd 201707222358.mp4
ddrescue -P -i 2115861172224 -s 262144 -o 17629184 ST3000DM001-2.dd 201707222358.mp4
ddrescue -P -i 2115861499904 -s 65536 -o 17891328 ST3000DM001-2.dd 201707222358.mp4
ddrescue -P -i 2115861630976 -s 196608 -o 17956864 ST3000DM001-2.dd 201707222358.mp4
ddrescue -P -i 2115862024192 -s 131072 -o 18153472 ST3000DM001-2.dd 201707222358.mp4
...
ddrescue -P -i 2327182266368 -s 36864 -o 883752960 ST3000DM001-2.dd 201707222358.mp4
(Total size of that file : 883787365, or 883789824 with the slack space.)
(“-P” stands for “preview”, “-i” for “input position”, “-s” for “size”, “-o” for “output position”.)
(The paths could be omitted as the scripts, the image file and the expected output files were all in the same directory.)
– 然后第一次尝试产生了一个不可读的文件,没有正确的 MP4 标头。为什么?因为 Hard Disk Sentinel 提供的列表给出了物理/绝对扇区号,但逻辑簇号(我通过使用 WinHex 打开图像文件进行了验证),所以我必须将 264192x512 添加到输入偏移量计算中(分区偏移量为 264192 个扇区,即 129MB)。
– 然后它就成功了。只花了几分钟就生成了五个视频文件,这些文件大部分都是可读的,可以跳到最后,并且包含预期的内容——我还没有完全看完,但它看起来已经完美无缺了。
(我在运行 Knoppix live 的辅助计算机上通过存储卡完成了所有这些操作,并使用 TeamViewer 从我的 Windows 7 主计算机上对其进行命令,并且能够轻松传输脚本文件。也许有更简单的设置来实现这样的目的,但是,好吧,它有效!:^p)
– 但当然有损坏的部分,因为该部分映像中存在不可读的扇区。我如何快速可靠地知道在哪里?好吧......
我想到使用 ddrescue 的“生成”模式,该模式通过解析输出并认为完全空白的扇区是未读扇区(标记为“?”,其余标记为“+”)来创建日志文件(或现在称为 mapfile)。由于 ddrescue 需要一个输入文件和一个输出文件,但实际上在该模式下只解析输出文件,我使用此命令创建了虚拟输入文件,它只复制 1MB,但将大小扩展到输出文件的大小(只是为了节省时间和空间):
ddrescue -s 1048576 -x 883789824 201707222358.mp4 201707222358copy.mp4
然后我运行“generate”命令:
ddrescue -G 201707222358copy.mp4 201707222358.mp4 201707222358-generate.log
然后我用 ddrescueview 打开了这些文件:
(六个文件中有三个像上面第一个一样损坏严重,有大量空数据,另外三个像第二个一样只有几个损坏的扇区。第二个文件没有碎片,我用一个 ddrescue 命令提取了它。)
然后我一边为自己感到庆幸,一边又为自己几个月来每天都使用那块 3TB 的硬盘而感到惭愧,因为之前我并没有备份……(起初它应该只用来存储临时内容,而我会在其他硬盘上腾出空间,但这比预期的要长,最终我没有空间来存储这些视频,甚至在某个时候我的个人照片和视频,这可能是一场大灾难,但正如迪克·琼斯所说的那样,“这只是一个小故障”。)