Actually, you can’t! This is what one of the developers, Andreas Dilger, said about it:
In order to ensure that ext3 can safely resume an unlink after a crash, it actually zeros out the block pointers in the inode, whereas ext2 just marks these blocks as unused in the block bitmaps and marks the inode as “deleted” and leaves the block pointers alone.
Your only hope is to “grep” for parts of your files that have been deleted and hope for the best.
但是,但是,这不是事实的全部,被删除文件的所有信息可能都还在磁盘上,包括块指针。ext3grep通过分析文件系统日志,实现了恢复被删除文件的功能。
一、原理
Carlo Wood在2008年2月7日不小心使用了rm -rf 删除了/home目录,损失数据超过3GB,而唯一的备份还是2007年6月份的,他不甘心他的数据就这么丢失,于是就还是研究ext3文件系统,牛人就是牛人,他花了3个星期,写了将近5000行代码,他恢复了所有的文件。
ext3grep工具的恢复原理并不是依赖特定文件格式。以ext3grep为例,他首先通过文件系统的root
inode(一般为2)来获得所有当前文件系统下文件的信息,包括存在的和已经删除的,这些信息当然也包括文件名和其inode。
然后利用inode到日志来去查询该inode所在的block位置,包括直接块,间接块等信息。最后利用dd来将这些信息dump出来,而形成一个文件。
ext3grep官方网站:http://code.google.com/p/ext3grep/
二、步骤
光说不练是假把式,我们就祭出他的工具–ext3grep。如果你是debian/ubuntu用户,那你走运了,直接sudo apt-get install ext3grep就可以了。
我们可以一步一步的从文件系统原理来告诉你如何恢复一个文件,但是我怕你还没有看完,就走人了,所以我就先给一个快速演示给大家看看:我们先删除/boot目录(/dev/sda2分区)下的某一个文件(如果你不相信他能恢复,请先行备份),然后利用这个工具来恢复这个文件。
1)备份并删除文件
root@wgzhao-nb:/boot# mount -o rw,remount /dev/sda2 /boot
root@wgzhao-nb:/boot# rm -rf initrd.img-2.6.28-13-generic
root@wgzhao-nb:/boot# sync
2)如果你为了保险其间,可以立刻将boot分区(/dev/sda2)挂载为只读
3)假定你不记得你要恢复的文件的名字了(大部分情况是不会记得的),我们要列出包含删除文件目录下所有包含的文件,包括被删除的文件。
Running ext3grep version 0.10.1
WARNING: I don't know what EXT3_FEATURE_COMPAT_EXT_ATTR is.
Number of groups: 13
Minimum / maximum journal block: 527 / 4641
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1246156824 = Sun Jun 28 10:40:24 2009
Number of descriptors in journal: 364; min / max sequence numbers: 310 / 883
Finding all blocks that might be directories.
[...]
System.map-2.6.18-128.1.14.el5
System.map-2.6.18-53.11AXS3
System.map-2.6.28-13-generic
System.map-2.6.28-14-generic
System.map-2.6.30-10-generic
System.map-2.6.30-10-generic.dpkg-new
System.map-2.6.30-10-generic.dpkg-tmp
[...]
lost+found
module-info
symvers-2.6.18-128.1.14.el5.gz
symvers-2.6.18-53.11AXS3.gz
vmcoreinfo-2.6.28-13-generic
vmcoreinfo-2.6.28-14-generic
vmcoreinfo-2.6.30-10-generic
vmcoreinfo-2.6.30-10-generic.dpkg-new
vmcoreinfo-2.6.30-10-generic.dpkg-tmp
vmlinuz
vmlinuz-2.6.18-128.1.14.el5
vmlinuz-2.6.18-53.11AXS3
vmlinuz-2.6.28-13-generic
vmlinuz-2.6.28-14-generic
vmlinuz-2.6.30-10-generic
vmlinuz-2.6.30-10-generic.dpkg-tmp
4)看了这个列表你总知道你要恢复的文件名字了吧,我们这里是initrd.img-2.6.28-13-generic,如果你还是不记得,唉,好人做到底,给你必杀技,使用下面的指令:
Running ext3grep version 0.10.1
WARNING: I don't know what EXT3_FEATURE_COMPAT_EXT_ATTR is.
Number of groups: 13
Loading group metadata... done
Minimum / maximum journal block: 527 / 4641
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1246156824 = Sun Jun 28 10:40:24 2009
Number of descriptors in journal: 364; min / max sequence numbers: 310 / 883
Inode is Allocated
Finding all blocks that might be directories.
D: block containing directory start, d: block containing more directory entries.
Each plus represents a directory start that references the same inode as a directory start that we found previously.
Writing analysis so far to 'sda2.ext3grep.stage2'. Delete that file if you want to do this stage again.
The first block of the directory is 513.
Inode 2 is directory "".
Directory block 513:
.-- File type in dir_entry (r=regular file, d=directory, l=symlink)
| .-- D: Deleted ; R: Reallocated
Indx Next | Inode | Deletion time Mode File name
==========+==========+----------------data-from-inode------+-----------+=========
0 1 d 2 drwxr-xr-x .
1 end d 2 drwxr-xr-x ..
6 7 r 14 D 1248245870 Wed Jul 22 14:57:50 2009 rrw-r--r-- symvers-2.6.18-53.11AXS3.gz
15 16 r 6058 D 1248086531 Mon Jul 20 18:42:11 2009 rrw-r--r-- vmlinuz-2.6.28-13-generic
16 17 r 6063 D 1248086910 Mon Jul 20 18:48:30 2009 rrw-r--r-- System.map-2.6.28-13-generic
17 18 r 6054 D 1248086910 Mon Jul 20 18:48:30 2009 rrw-r--r-- initrd.img-2.6.28-13-generic
18 19 r 6059 D 1248086557 Mon Jul 20 18:42:37 2009 rrw-r--r-- config-2.6.28-13-generic
19 20 r 6064 D 1248086910 Mon Jul 20 18:48:30 2009 rrw-r--r-- vmcoreinfo-2.6.28-13-generic
22 23 r 6057 D 1248086910 Mon Jul 20 18:48:30 2009 rrw-r--r-- abi-2.6.28-13-generic.dpkg-tmp
24 26 r 6056 D 1248086910 Mon Jul 20 18:48:30 2009 rrw-r--r-- config-2.6.28-13-generic.dpkg-tmp
[...]
以上你看到的D标志的,就是被删除的文件,这你总知道了吧,还是不知道,那就再往后看,最后有一个必必杀计。
5)接着我们恢复文件,这是关键:
root@wgzhao-nb:/tmp# ext3grep $IMAGE --restore-file initrd.img-2.6.28-13-generic
[...]
Restoring initrd.img-2.6.28-13-generic
root@wgzhao-nb:/tmp# md5sum RESTORED_FILES/initrd.img-2.6.28-13-generic
22092b1719a7601674fc59ff4a534dc9 RESTORED_FILES/initrd.img-2.6.28-13-generic
root@wgzhao-nb:/tmp# md5sum /var/tmp/initrd.img-2.6.28-13-generic
22092b1719a7601674fc59ff4a534dc9 /var/tmp/initrd.img-2.6.28-13-generic
由此我们知道恢复出来的文件是完整的。这里要注意的是–restore-file 的文件参数,文件参数应该包括文件相对路径,相对路径指的是相对你指定的设备,比如/dev/sda2就是/boot的根目录,而initrd.img-2.6.28-13-generic在/boot目录下,因此这里直接给出文件名就好了,如果是需要恢复/boot/grub/grub.conf文件的话,那么指定的参数就应该像下面这样:
细心的你,你可能知道了,他指定文件的方式就和grub一样,比如(hd0,1)/grub/grub.conf这样。
以上是恢复一个文件的简单步骤,如果你想从ext3文件系统原理着手来看如何逐步恢复一个文件的话,请看ext3grep的作者自己写的howto,那里给出了一个非常详细的步骤,使得你对ext3文件系统一定有更深入的了解。
如果你有N个文件需要恢复(N>100),那么用上面的方法看就比较恼火了,所以作者给ext3grep增加了一个–restore-all的参数。它能把指定设备的所有看你能恢复的文件都恢复出来,写入一个RESTORED_FILES目录里。作者建议使用–restore-all的参数时,同时指定–after参数,表示指定恢复什么时间之后被删除的文件,这是为了防止用恢复过多的旧文件,算是一种过滤方式。参数为时间戳格式,比如:
表示恢复自2009-06-22 21:07以后删除的文件。
OK,更详细更强大的功能,自己去看作者的howto吧。
三、在红旗上使用
红旗 Linux上也可以使用该工具,具体的使用方法,请参考:
http://blog.chinaunix.net/u2/85323/showart_2002696.html
四、命令总结
[root@xhy-1 boot]# cd /boot/
[root@xhy-1 boot]# cp -r initrd-2.6.18-194.el5.img /opt/
[root@xhy-1 boot]# md5sum initrd-2.6.18-194.el5.img
[root@xhy-1 boot]# mount
/dev/sda3 on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/sda1 on /boot type ext3 (rw)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
[root@xhy-1 boot]# mount -o rw,remount /dev/sda1
[root@xhy-1 boot]# rm -rf initrd-2.6.18-194.el5.img
[root@xhy-1 boot]# sync
[root@xhy-1 boot]# mount -o ro,remount /dev/sda1
[root@xhy-1 boot]# mount
/dev/sda3 on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/sda1 on /boot type ext3 (ro)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
[root@xhy-1 boot]# ext3grep /dev/sda1 --dump-names
[root@xhy-1 opt]# cd /
[root@xhy-1 /]# ext3grep /dev/sda1 --restore-file initrd-2.6.18-194.el5.img
Running ext3grep version 0.10.2
[root@xhy-1 /]# pwd
/
[root@xhy-1 /]# cd RESTORED_FILES/
[root@xhy-1 RESTORED_FILES]# ls
initrd-2.6.18-194.el5.img
[root@xhy-1 RESTORED_FILES]# md5sum initrd-2.6.18-194.el5.img
[root@xhy-1 RESTORED_FILES]# mount -o rw,remount /dev/sda1
[root@xhy-1 RESTORED_FILES]# cp -r initrd-2.6.18-194.el5.img /boot/