ext2文件系统:实战分析ext2文件系统下恢复误删除文件

作者:linuxaid

本系 BBS 系统真是多灾多难 (嗯....其实是疏忽才会这么多灾多难 ....)继这几日系统时间不正确造成许多人ID误砍后次因系统设定上问题将BBS重要备份档给杀了这件事是学弟发现后告诉我当我上站来见到他 mail, 当真是欲哭无泪差点没去撞墙

  那时已是周 6晚11:00左右边想着要编套说辞向大家解释无法替大家恢复旧信件和设定了边还在想是否能够挽回局面大家知道UNIXlike系统是很难像 M$ 系统做到 undelete 所有网管前辈都曾再 3警告我们要小心! 小心!砍档的前 3思而后行砍了的后再后悔也没用虽然我已渐渐做到砍档 3思而后行但的次误砍事件是系统在背景中定时执行等到我找出原因时已是档案被砍后个多小时

  我凭着点点印象想起在网络上有人讨论过在 Linux ext2 filesystem中 undelete可能性但我所见到多半是负面答案但好象真有人做过这件事于是我第个所做就是马上将该档案原来所在 partition mount成 read-only, 禁止任何写入动作不是怕再有档案被误砍(已没什么可砍了)而是怕有新档案写进来新资料可能会覆盖到旧资料原本存在磁区(block)我们现在唯个指望就是企图将档案原来存在磁区个个找回来并且「希望」这些磁区上旧资料都还在然后将这些磁区串成个档案终于被我找到了!!原来这方面技术文件就存在我自己系统中 :-)) /usr/doc/HOWTO/mini/Ext2fs-ndeletion.gz

  于是我就按照这份文件指示步步来总算将个长达 8MB 压缩档救回了 99%, 还有个长达 1.1 MB 压缩档完整无缺地救了回来感谢上帝、 Linux 设计者、写那篇文件作者、曾经讨论过此技术人、以及 Linux 如此优秀 ext2filesystem,让我有机会抢救过去现在我将我抢救步骤做个整理让大家参考希望有派得上用场时候 (喔! 不最好是希望大家永远不要有机会用到以下步数 :-))) 在此严正声明!! 写这篇文章是给那些处于万不得已情况下人们个挽回机会并不意味着从此我们就可以大意砍档不需要 3思前面提到我有个档案无法100%救回事实上长达 8MB 档案能救回 99% 已是幸运中幸运情况下若能救回 70% - 80% 已经要愉笑了所以不要指望 undelete 能救回预防胜于治疗! 请大家平时就养成好习惯砍档前请 3思!!!

理论分析

  我们能救回机会有多大? 在 kernel-2.0.X 系列中 (本站所用 kernel 是 2.0.33) 取决以下两点:

  档案原来所在磁区是否没有被覆写?

  档案是否完全连续?

  第点我们可以和时间竞赛就是当发现档案误砍时要以最快速度 umount 该filesystem,或将该filesystemremount成唯读就这次情况而言档案误砍是在事发个小时后才发现但由于该filesystem写入机会很少(我几乎可确定天才只有做 backup)所以第点算是过关了

  第 2点真是要听天由命了就本站所使用kernel,必须要在假设「长档案」所占 block 完全连续情况下才有可能完全救回来! 个 block 是 1024 s,长达 8 MB档案就有超过 8000 个 block在经常读写 filesystem 中可以想见长档案很难完全连续但在我们系统中点似乎又多了几分指望同时Linuxext2如此精良filesystem,能做到前7950多个block都连续点也功不可没

  好了以下我就讲下我步骤

  抢救步骤 I - mount filesystem readonly

  该档案位置原来是在 /var/hda/backup/home/bbs 下我们系统filesystem 组态是:



root@bbs:/home/ftp/rescue# df Filesystem 1024-blocks Used Available Capacity Mounted _disibledevent=> debugfs: 92 deleted inodes found. Inode Owner Mode Size Blocks Time deleted .................................................................... 29771 0 100644 1255337 14/14 Sat Jan 30 22:37:10 1999 29772 0 100644 5161017 14/14 Sat Jan 30 22:37:10 1999 29773 0 100644 8220922 14/14 Sat Jan 30 22:37:10 1999 29774 0 100644 5431 6/6 Sat Jan 30 22:37:10 1999





  请注意!我们必须要在档案大小、被砍时间等资讯中判断出要救回档案是那在此我们要救回 29773 这个 inode

抢救步骤 III

  执行 echo "stat <29773>" | debugfs /dev/hda1

  列出该 inode 所有资讯如下:



debugfs: stat <29773> Inode: 29773 Type: regular Mode: 0644 Flags: 0x0 Version: 1 User: 0 Group: 0 Size: 8220922 File ACL: 0 Directory ACL: 0 Links: 0 Blockcount: 16124 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x36b31916 -- Sat Jan 30 22:37:10 1999 atime: 0x36aebee4 -- Wed Jan 27 15:23:16 1999 mtime: 0x36adec25 -- Wed Jan 27 00:24:05 1999 dtime: 0x36b31916 -- Sat Jan 30 22:37:10 1999 BLOCKS: 123134 123136 123137 123138 123140 131404 131405 131406 131407 131408 131409 131 410 131411 131668 TOTAL: 14







  现在重点是必须将该inode所指档案所指block全部找回来在这它?14


 

个block?不对啊!应该要有8000多个block才对啊!在这Filesystem奥妙了上头所列前 12 个 block 是真正指到档案资料 block, 称的为 direct block 第 13个称为第阶 indirect block, 第 14 个称为第 2阶 indirect block 什么意思? 该档案资料所在 block 位置如下:

  各位明白吗? 第 13 个 (131411) 和第 14 个 block 其实不是 data, 而是 index,它指出接下来 block 位置由于个 block 大小是 1024 s, 在 32 位系统中是 4 s, 故个 block 可以记录 256 笔资料以 131411 block 为例它所记录资料即为 (在档案未砍前): 131412 131413 131414 .... 131667 (共 256 笔)

  而这256个block就真正记录了档案资料所以我们称为第同理第 2阶就有

两个层 index, 以 131668 来说它可能记录了: 131669 131926 132182 .... (最多有 256 笔)

  而 131669 block 记录为: 131670 131671 131672 .... 131925 (共 256笔)而这256个block才是真正储存档案资料而我们要就是这些真正储存档案资料block理论上我们只要将这些indexblock内容全部读出来然后照这些 index把所有block全部读到手就能100%救回档案(假设这些block全部没有被新档案覆写话)工程很大但是可行不幸在 kernel-2.0.33, 其设计是如果该档案被砍了则这些 index block 全部会规零因此我所读到是 0 0 0 0 0 ..... (共 256 笔)

  哇!没办法知道这些datablock真正所在位置所以在此我们做了个很大

设:整个档案所在block是连续!也就是我上头例子这也就是为什么说只有连续block(是指后头indirectblock)档案才能完整救回而这点就要听天由命了

抢救步骤 IV

  好了现在我们只好假设所有档案处于连续block上现在请用http://archie.ncu.edu.tw去找这个工具:fsgrab-1.2.tar.gz,并将它安装起来步骤很简单故在此我就不多谈我们要用它将所需 block 全部抓出来使用方法如下: fsgrab -c count -s skip device

  其中 count 是只要 (连续) 读几个 skip是指要从第几个开始读例如我要从 131670 开始连续读 256 个就这样下指令: fsgrab -c 256 -s 131670 /dev/hda1 > recover

  现在我们就开始救档案吧! 以上头资料我们必须用以下指令来救: (注意到头开 12 个 block 并没有完全连续!!!)

fsgrab -c 1 -s 123134 /dev/hda1 > recover fsgrab -c 3 -s 123136 /dev/hda1 >> recover fsgrab -c 1 -s 123140 /dev/hda1 >> recover fsgrab -c 7 -s 131404 /dev/hda1 >> recover





  这是开头 12 个 block, 对于第阶 indirect, 就资料来看好象是连续 :-)) fsgrab -c 256 -s 131412 /dev/hda1 >> recover

  注意要跳过 131411, 它是 index block对于第 2阶 indirect, 我们 *假设* 它们都是连续:

fsgrab -c 256 -s 131670 /dev/hda1 >> recover fsgrab -c 256 -s 131927 /dev/hda1 >> recover fsgrab -c 256 -s 132184 /dev/hda1 >> recover ............................................





  要直做直到 recover 大小超过我们所要救回档案大小(8220922)为止要跳过那些 index block (如 131668, 131669, 131926, 132183, ....) 了

抢救步骤 V

  最后就是把档案「剪」出来并看看我们救回多少了我们重复上述步骤弄出来 recover 档大小为8294400而我们要大小是8220922,那就这样下指令:

split -b 8220922recover rec

则会做出两个档个是recaa,大小是8220922,另个是recab则是剩下大小后者是垃圾扔了即可现在我们可以检查这个档案是不是「完整」那个被误砍档案了由于我们那个档案是 .tar.gz 格式于是我们这个思路方法来检查:

mv recaa recaa.tar.gz

zcat recaa.tar.gz > recaa.tar

  如果没有讯息那表示成功了!完全救回来了但不幸我们没有成功将弄出 recaa.tar 改名再 gzip 的后和原来 recaa.tar.gz 比下大小发现少了 1%, 表示说该档原来所在 block 中最后有 1% 是不连续 (或者被新写入档案覆写了)但这已是不幸中大幸了

  后记

  对于在 undelete时假设所有 block 连续问题那份 HOWTO 文件说Linus和其它kernel设计者正着手研究看能否克服这个困难也就是在档案砍掉时不要将indexblock规零我刚刚试下kenrel-2.2.0环境发现已做到了!! 以下是个已砍档案 inode data (由 debugfs 所读出):

debugfs: Inode: 36154 Type: regular Mode: 0600 Flags: 0x0 Version: 1 User: 0 Group: 0 Size: 2165945 File ACL: 0 Directory ACL: 0 Links: 0 Blockcount: 4252 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x36b54c3b -- Mon Feb 1 14:39:55 1999 atime: 0x36b54c30 -- Mon Feb 1 14:39:44 1999 mtime: 0x36b54c30 -- Mon Feb 1 14:39:44 1999 dtime: 0x36b54c3b -- Mon Feb 1 14:39:55 1999 BLOCKS: 147740 147741 147742 147743 147744 147745 147746 147747 147748 147769 147770 157642 157643 157644 157645 157646 157647 157648 157649 157650 157651 157652 157653 157654 157655 157656 157657 157658 157659 157660 157661 157662 157663 157664 157665 157666 157667 157668 157669 157670 157671 157672 157673 157674 157675 157676 157677 157678 157679 157680 157681 157682 157683 157684 157685 157686 157687 1................... .........9745 159746 159747 159748 159749 159750 159751 159752 159753 159754 159755 159756 TOTAL: 2126





  真是太完美了!! 这意味着在 kernel-2.2.X 环境下我们不必假设所有 block 都连续而且可以百分的百找回所有砍掉 block! 因此上述第 2个风险就不存在了

  以上资料谨供参考

  参考文件: Ext2fs-Undeletion Mini HOWTO





Tags:  文件系统raw 文件系统 恢复文件系统 ext2文件系统

延伸阅读

最新评论

发表评论