ext2文件系统下恢复误删除的文件,摘要ext2

文件 2
文件系统下恢复误删除的文件 --------------------------------------------------------------------- 本系的BBS系统真是多灾多难(嗯....其实是因为我的疏忽,才会这么多灾多难....),继这几日系统时间不正确,造成许多人的ID被误砍后,又一次因系统设定上的问题,将BBS的重要备份档给杀了。
这件事是学弟发现后告诉我的,当我上站来一见到他的mail,当真是欲哭无泪,差点没去撞墙。
那时已是周六晚11:00左右,我一边想着要编一套说辞向大家解释无法替大家恢复旧信件与设定了,一边还在想是否能够挽回局面。
大家知道,UNIXlike的系统是很难像M$的系统一样,做到undelete的,所有网管前辈都曾再三警告我们,要小心!
小心!
砍档之前三思而后行,砍了之后再后悔也没用。
虽然我已渐渐做到砍档三思而后行,但之次误砍事件是系统在背景中定时执行的,等到我找出原因时已是档案被砍后一个多小时。
我凭着一点点的印象,想起在网络上,有人讨论过在Linuxext2filesystem中undelete的可能性,但我所见到的多半是负面的答案,但好象真的有人做过这件事,于是我第一个所做的,就是马上将该档案原来所在的partitionmount成read-only,禁止任何的写入动作,不是怕再有档案被误砍(因为已没什么可砍的了),而是怕有新档案写进来,新资料可能会覆盖到旧资料原本存在的磁区(block)。
我们现在唯一个指望,就是企图将档案原来存在的磁区一个个找回来,并且「希望」这些磁区上的旧资料都还在,然后将这些磁区串成一个档案。
终于被我找到了!
!
原来这方面的技术文件就存在我自己的系统中:-)) /usr/doc/HOWTO/mini/Ext2fs-Undeletion.gz 于是我就按照这份文件的指示一步步来,总算将一个长达8MB的压缩档救回了99%,还有一个长达1.1MB的压缩档完整无缺地救了回来。
感谢上帝、Linux的设计者、写那篇文件的作者、曾经讨论过此技术的人、以及Linux如此优秀的ext2filesystem,让我有机会抢救过去。
现在,我将我的抢救步骤做一个整理让大家参考,希望有派得上用场的时候(喔!
不,最好是希望大家永远不要有机会用到以下的步数:-))) 在此严正声明!
!
写这篇文章的目的,是给那些处于万不得已情况下的人们,有一个挽回的机会,并不意味着从此我们就可以大意,砍档不需要三思。
前面提到,我有一个档案无法100%救回,事实上,长达8MB的档案能救回99%已是幸运中的幸运,一般的情况下若能救回70%-80%已经要愉笑了。
所以,不要指望undelete能救回一切。
预防胜于治疗!
请大家平时就养成好习惯,砍档前请三思!
!
!
理论分析 我们能救回的机会有多大?
在kernel-2.0.X系列中(本站所用的kernel是2.0.33),取决以下两点: 档案原来所在的磁区是否没有被覆写?
档案是否完全连续?
第一点我们可以与时间竞赛,就是当一发现档案误砍时,要以最快的速度umount该filesystem,或将该filesystemremount成唯读。
就这次的情况而言,档案误砍是在事发一个小时后才发现的,但由于该filesystem写入的机会很少(我几乎可确定一天才只有一次,做backup),所以第一点算是过关了。
第二点真的是要听天由命了,就本站所使用的kernel,必须要在假设「长档案」所占的block完全连续的情况下,才有可能完全救回来!
一个block是1024bytes,长达8MB的档案就有超过8000个block。
在经常读写的filesystem中,可以想见长档案很难完全连续,但在我们的系统中,这一点似乎又多了几分指望。
同时,Linuxext2如此精良的filesystem,能做到前7950多个block都连续,这一点也功不可没。
好了,以下我就讲一下我的步骤。
抢救步骤I-mountfilesystemreadonly该档案的位置原来是在/var/hda/backup/home/bbs下,我们系统的filesystem组态是: root@bbs:/home/ftp/rescue#dfFilesystem1024-blocksUsedAvailableCapacityMountedon/dev/sda13965003127696325083%//dev/sda377741053763319961573%/home/dev/hda11990473692715184020%/var/hda/dev/hda2102902349099848571050%/home/ftp 因此/var/hda这个filesystem要马上mount成readonly(以下请用root身份): mount-oremount,ro/var/hda 当然也可以直接umount它,但有时候可能有某些process正在此filesystem下运作,您可能无法直接umount它。
因此我选择mountreadonly。
但您也可以用: fuser-v-m/usr 看一下目前是那些process在用这个filesystem,然后一一砍掉,再umount。
抢救步骤II执行 echolsdel|debugfs/dev/hda1|less 看一下该filesystem最近被砍的inode(档案)有那些(为什么是/dev/hda1?
请见上头的df列表)?
在这奶F档案的重要资讯,如大小、时间、属性等等。
就我们的系统而言,其列示如下: debugfs:92deletedinodesfound.InodeOwnerModeSizeBlocksTimedeleted....................................................................297710100644125533714/14SatJan3022:37:101999297720100644516101714/14SatJan3022:37:101999297730100644822092214/14SatJan3022:37:10199929774010064454316/6SatJan3022:37:101999 请注意!
我们必须要在档案大小、被砍时间等资讯中判断出要救回的档案是那一个。
在此,我们要救回29773这个inode。
抢救步骤III执行 echo"stat<29773>"|debugfs/dev/hda1 列出该inode的所有资讯,如下: debugfs:stat<29773>Inode:29773Type:regularMode:0644Flags:0x0Version:1User:0Group:0Size:8220922FileACL:0DirectoryACL:0Links:0Blockcount:16124Fragment:Address:0Number:0Size:
0 ctime:0x36b31916--SatJan3022:37:101999atime:0x36aebee4--WedJan2715:23:161999mtime:0x36adec25--WedJan2700:24:051999dtime:0x36b31916--SatJan3022:37:101999BLOCKS:123134123136123137123138123140131404131405131406131407131408131409131410131411131668TOTAL:14 现在的重点是,必须将该inode所指的档案,所指的block全部找回来。
在这它?
14个block?
不对啊!
应该要有8000多个block才对啊!
在这卯ilesystem的「奥密」了。
上头所列的前12个block是真正指到档案资料的block,称之为directblock。
第13个称为第一阶indirectblock,第14个称为第二阶indirectblock。
什么意思?
该档的资料所在的block位置如下: 各位明白吗?
第13个(131411)与第14个block其实不是data,而是index,它指出接下来的block的位置。
由于一个block的大小是1024bytes,一个int在32位系统中是4bytes,故一个block可以记录256笔资料。
以131411block为例,它所记录的资料即为(在档案未砍前): 131412131413131414....131667(共256笔) 而这256个block就真正记录了档案资料,所以我们称为第一阶。
同理,第二阶就有两个层index,以131668来说,它可能记录了: 131669131926132182....(最多有256笔) 而131669的block记录为: 131670131671131672....131925(共256笔) 而这256个block才是真正储存档案资料的。
而我们要的,就是这些真正储存档案资料的block。
理论上,我们只要将这些indexblock的内容全部读出来,然后照这些index把所有的block全部读到手,就能100%救回档案(假设这些block全部没有被新档案覆写的话)。
工程很大,但是可行。
不幸的是,在kernel-2.0.33,其设计是,如果该档案被砍了,则这些indexblock全部会规零,因此我所读到的是 00000.....(共256笔) 哇!
没办法知道这些datablock真正所在的位置。
所以,在此我们做了一个很大的假设:整个档案所在的block是连续的!
也就是我上头的例子。
这也就是为什么说,只有连续block(是指后头的indirectblock)的档案才能完整救回,而这一点就要听天由命了。
抢救步骤IV好了,现在我们只好假设所有的档案处于连续的block上,现在请用http://archie.ncu.edu.tw/去找这个工具:fsgrab-1.2.tar.gz,并将它安装起来。
因为步骤很简单,故在此我就不多谈。
我们要用它将所需的block全部抓出来。
它的用法如下: fsgrab-ccount-sskipdevice 其中count是只要(连续)读几个,skip是指要从第几个开始读,例如我要从131670开始连续读256个,就这样下指令: fsgrab-c256-s131670/dev/hda1>recover 现在我们就开始救档案吧!
以上头的资料,我们必须用以下的指令来救:(注意到头开的12个block并没有完全连续!
!
!
) fsgrab-c1-s123134/dev/hda1>recoverfsgrab-c3-s123136/dev/hda1>>recoverfsgrab-c1-s123140/dev/hda1>>recoverfsgrab-c7-s131404/dev/hda1>>recover 这是开头的12个block,对于第一阶indirect,就资料来看好象是连续的:-)) fsgrab-c256-s131412/dev/hda1>>recover 注意要跳过131411,因为它是indexblock。
对于第二阶indirect,我们*假设*它们都是连续的: fsgrab-c256-s131670/dev/hda1>>recoverfsgrab-c256-s131927/dev/hda1>>recoverfsgrab-c256-s132184/dev/hda1>>recover............................................ 要一直做,直到recover的大小超过我们所要救回的档案大小(8220922)为止。
要注意在这市p心地跳过那些indexblock(如131668,131669,131926,132183,....)了。
抢救步骤V最后一步,就是把档案「剪」出来,并看看我们救回多少了。
在这戊]我们重复上述步骤,弄出来的recover档大小为8294400,而我们要的大小是8220922,那就这样下指令: split-b8220922recoverrec 则会做出两个档,一个是recaa,大小是8220922,另一个是recab则是剩下的大小,后者是垃圾,扔了即可。
现在我们可以检查这个档案是不是「完整」的那个被误砍的档案了。
由于我们的那个档案是.tar.gz的格式,于是我们这个方法来检查: mvrecaarecaa.tar.gzzcatrecaa.tar.gz>recaa.tar 如果没有错误讯息,那表示成功了!
完全救回来了。
但不幸的是,我们没有成功,将弄出的recaa.tar改名再gzip之后,与原来的recaa.tar.gz比一下大小,发现少了1%,表示说该档原来所在的block中最后有1%是不连续的(或者被新写入的档案覆写了),但这已是不幸中的大幸了。
后记对于在undelete时*必需*假设所有block连续的问题,那份HOWTO文件说Linus与其它kernel设计者正着手研究,看能否克服这个困难,也就是在档案砍掉时,不要将indexblock规零。
我刚刚试
下kenrel-2.2.0的环境,发现已做到了!
!
以下是一个已砍的档案的inodedata(由debugfs所读出): debugfs:Inode:36154Type:regularMode:0600Flags:0x0Version:1User:0Group:0Size:2165945FileACL:0DirectoryACL:0Links:0Blockcount:4252Fragment:Address:0Number:0Size:0ctime:0x36b54c3b--MonFeb114:39:551999atime:0x36b54c30--MonFeb114:39:441999mtime:0x36b54c30--MonFeb114:39:441999dtime:0x36b54c3b--MonFeb114:39:551999BLOCKS:1477401477411477421477431477441477451477461477471477481477691477701576421576431576441576451576461576471576481576491576501576511576521576531576541576551576561576571576581576591576601576611576621576631576641576651576661576671576681576691576701576711576721576731576741576751576761576771576781576791576801576811576821576831576841576851576861576871............................9745159746159747159748159749159750159751159752159753159754159755159756TOTAL:2126 真是太完美了!
!
这意味着在kernel-2.2.X的环境下,我们不必假设所有的block都连续,而且可以百分之百找回所有砍掉的block!
因此上述的第二个风险就不存在了。
以上资料,谨供参考。
数据恢复:北亚数据恢复技术站

标签: #过大 #平板 #文件 #苹果 #文件 #压缩文件 #文件转换成 #机上