一:Ext3grep
注明:ext3grep是一个开源的ext3文件系统反删除工具,在ext3grep出现之前,数据被删除后,通过常规手段恢复基本上不可能的,虽然debugfs命令可以对ext2文件系统做一些恢复,但对ext3文件系统就不能无力了。ext3是一个日志文件系统,ext3grep正是通过分析ext3文件系统的日志信息来恢复被删除的文件和数据。
Ext3grep安装步骤
操作系统: centos 5.4
ext3grep 版本:ext3grep-0.10.2
下载地址:http://code.google.com/p/ext3grep/downloads/detail?name=ext3grep-0.10.2.tar.gz
[root@localhost ~]# rpm -qa | grep e2fsprogs
e2fsprogs-devel-1.39-23.el5
e2fsprogs-libs-1.39-23.el5
e2fsprogs-1.39-23.el5
[root@localhost ~]# tar -zxvf ext3grep-0.10.2.tar.gz
[root@localhost ~]# cd ext3grep-0.10.2
[root@localhost ~]# ./configure
[root@localhost ~]# make
[root@localhost ~]# make install
[root@localhost ~]# ext3grep -v #检查版本
Running ext3grep version 0.10.2
ext3grep v0.10.2, Copyright (C) 2008 Carlo Wood.
ext3grep comes with ABSOLUTELY NO WARRANTY;
This program is free software; your freedom to use, change
and distribute this program is protected by the GPL.
Ext3grep到此安装完成,默认ext3grep命令放在/usr/local/bin 目录下。
1:下面通过删除文件盒目录案例说明Ext3grep使用:
(1)模拟数据误删除环境,详细介绍ext3grep恢复数据文件过程并挂在一块虚拟2G硬盘,划分一个分区/dev/sdb1 作为测试。
挂在新的分区
[root@localhost ~]# mkdir /test
[root@localhost ~]# mkfs.ext3 /dev/sdb1
[root@localhost ~]# mount /dev/sdb1 /test/
拷贝文件测试用
[root@localhost ~]# cp /etc/profile /test/
[root@localhost ~]# cp /boot/initrd-2.6.18-164.el5.img /test/
[root@localhost ~]# echo "ext3grep test" > /test/ext3grep.txt
[root@localhost ~]# mkdir /test/ext3grep
[root@localhost ~]#cp /etc/hosts /test/ext3grep
[root@localhost ~]# cd /test/
[root@localhost test]# ls -lh
total 3.2M
drwxr-xr-x 2 root root 4.0K Jun 20 19:03 ext3grep
-rw-r--r-- 1 root root 14 Jun 20 19:03 ext3grep.txt
-rw------- 1 root root 3.2M Jun 20 19:03 initrd-2.6.18-164.el5.img
drwx------ 2 root root 16K Jun 20 19:02 lost+found
-rw-r--r-- 1 root root 1.1K Jun 20 19:02 profile
[root@localhost test]# md5sum profile #获取文件效验码
a6e82d979bb95919082d9aceddf56c39 profile
[root@localhost test]# md5sum initrd-2.6.18-164.el5.img
cf423e478525d3d8960edd5f315e84a8 initrd-2.6.18-164.el5.img
[root@localhost test]# md5sum ext3grep.txt
5afe55495cdb666daad667e1cd797dcb ext3grep.txt
删除/test下所有文件
[root@localhost ~]# rm -rf /test/*
[root@localhost ~]# cd /test/
[root@localhost test]# ls
到此/test目录下没有文件和目录,下面我们就开始恢复所有文件和目录。
(2) 卸载/dev/sdb1分区
[root@localhost ~]# umount /test/
(3) 查询恢复数据信息
[root@localhost ~]# ext3grep /dev/sdb1 --ls --inode 2
Running ext3grep version 0.10.2
Number of groups: 16
Loading group metadata... done
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340190176 = Wed Jun 20 19:02:56 2012
Number of descriptors in journal: 59; min / max sequence numbers: 2 / 15
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.
Searching group 0: DD+++D+++
Searching group 1:
Searching group 2:
Searching group 3:
Searching group 4:
Searching group 5:
Searching group 6:
Searching group 7: +
Searching group 8:
Searching group 9:
Searching group 10:
Searching group 11:
Searching group 12:
Searching group 13:
Searching group 14:
Searching group 15:
Writing analysis so far to 'sdb1.ext3grep.stage1'. Delete that file if you want to do this stage again.
Result of stage one:
3 inodes are referenced by one or more directory blocks, 1 of those inodes is still allocated.
2 inodes are referenced by more than one directory block, 1 of those inodes is still allocated.
0 blocks contain an extended directory.
Result of stage two:
1 of those inodes could be resolved because it is still allocated.
1 inodes could be resolved because all refering blocks but one were journal blocks.
All directory inodes are accounted for!
Writing analysis so far to 'sdb1.ext3grep.stage2'. Delete that file if you want to do this stage again.
The first block of the directory is 643.
Inode 2 is directory "".
Directory block 643:
.-- 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 ..
2 3 d 11 D 1340190570 Wed Jun 20 19:09:30 2012 drwx------ lost+found
3 end r 12 D 1340190570 Wed Jun 20 19:09:30 2012 rrw-r--r-- profile
4 end r 13 D 1340190570 Wed Jun 20 19:09:30 2012 rrw------- initrd-2.6.18-164.el5.img
5 end r 14 D 1340190570 Wed Jun 20 19:09:30 2012 rrw-r--r-- ext3grep.txt
6 end d 114689 D 1340190570 Wed Jun 20 19:09:30 2012 drwxr-xr-x ext3grep
注明:“ext3grep /dev/sdb1 --ls --inode 2 ”主要用于扫描当前文件系统下所有文件的信息,包括存在的和已删除的文件,其中含有D表示就是已经删除的文件,如果不记得被删除的文件的名称,可以通过一下方式来查找:通过获取文件恢复的路径信息。
[root@localhost ~]# ext3grep /dev/sdb1 --dump-names
Running ext3grep version 0.10.2
Number of groups: 16
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340190176 = Wed Jun 20 19:02:56 2012
Number of descriptors in journal: 59; min / max sequence numbers: 2 / 15
Loading sdb1.ext3grep.stage2... done
ext3grep
ext3grep.txt
ext3grep/hosts
initrd-2.6.18-164.el5.img
lost+found
profile
(4)恢复单个文件
注明:要恢复被删除的某个文件,操作如下:
[root@localhost ~]# ext3grep /dev/sdb1 --restore-file ext3grep.txt
Running ext3grep version 0.10.2
Number of groups: 16
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340190176 = Wed Jun 20 19:02:56 2012
Number of descriptors in journal: 59; min / max sequence numbers: 2 / 15
Writing output to directory RESTORED_FILES/
Loading sdb1.ext3grep.stage2... done
Restoring ext3grep.txt
通过 “--restore-inode” 对应inode值即可恢复
[root@localhost ~]# ext3grep /dev/sdb1 --restore-inode 12
Running ext3grep version 0.10.2
Number of groups: 16
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340190176 = Wed Jun 20 19:02:56 2012
Number of descriptors in journal: 59; min / max sequence numbers: 2 / 15
Restoring inode.12
(5)恢复所有文件和目录
ext3grep /dev/sdb1 --restore-all
Running ext3grep version 0.10.2
Number of groups: 16
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340190176 = Wed Jun 20 19:02:56 2012
Number of descriptors in journal: 59; min / max sequence numbers: 2 / 15
Loading sdb1.ext3grep.stage2... done
Restoring ext3grep.txt
Restoring ext3grep/hosts
Restoring initrd-2.6.18-164.el5.img
Restoring profile
注明:“--restore-all”参数将指定存储设备中可以恢复的文件都恢复出来并放到了“RESTORED_FILES”目录中,“--restore-all”参数对恢复大量数据文件时非常有用。
(4) 查看是否恢复成功,在当前目录会生成一个目录“RESTORED_FILES”
[root@localhost ~]# cd RESTORED_FILES/
[root@localhost RESTORED_FILES]# ls -l
total 3252
drwxr-xr-x 2 root root 4096 Jun 20 19:32 ext3grep
-rw-r--r-- 1 root root 14 Jun 20 19:03 ext3grep.txt
-rw------- 1 root root 3304473 Jun 20 19:03 initrd-2.6.18-164.el5.img
-rw-r--r-- 1 root root 1029 Jun 20 19:02 inode.12
drwx------ 2 root root 4096 Jun 20 19:09 lost+found
-rw-r--r-- 1 root root 1029 Jun 20 19:02 profile
重新挂载分区并将恢复的文件和目录移动到原来的目录中,到此数据恢复完成。
[root@localhost RESTORED_FILES]# mount /dev/sdb1 /test/
[root@localhost RESTORED_FILES]# mv * /test/
[root@localhost RESTORED_FILES]# cd /test/
[root@localhost test]# ls
ext3grep ext3grep.txt initrd-2.6.18-164.el5.img inode.12 lost+found profile
[root@localhost test]# ls -lh
total 3.2M
drwxr-xr-x 2 root root 4.0K Jun 20 19:32 ext3grep
-rw-r--r-- 1 root root 14 Jun 20 19:03 ext3grep.txt
-rw------- 1 root root 3.2M Jun 20 19:03 initrd-2.6.18-164.el5.img
-rw-r--r-- 1 root root 1.1K Jun 20 19:02 inode.12
drwx------ 2 root root 4.0K Jun 20 19:09 lost+found
-rw-r--r-- 1 root root 1.1K Jun 20 19:02 profile
2:通过ext3grep恢复误删除的MYSQL表
实施步骤如下:
(1) 模拟MYSQL表被删除环境,注明:下面介绍在采用的是MyISAM存储引擎的mysql中模拟表被误删除的恢复过程。假设:mysql所在的磁盘分区为/dev/sdb1, 挂在到/test目录下。
(2)查看mysql数据库表信息
[root@localhost test]# mysql -u root -p
mysql> use mysql;
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| columns_priv |
| db |
| func |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| host |
| proc |
| procs_priv |
| tables_priv |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
17 rows in set (0.01 sec)
mysql> select * from host;
Empty set (0.01 sec)
mysql> desc host;
+-----------------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+---------------+------+-----+---------+-------+
| Host | char(60) | NO | PRI | | |
| Db | char(64) | NO | PRI | | |
| Select_priv | enum('N','Y') | NO | | N | |
| Insert_priv | enum('N','Y') | NO | | N | |
| Update_priv | enum('N','Y') | NO | | N | |
| Delete_priv | enum('N','Y') | NO | | N | |
| Create_priv | enum('N','Y') | NO | | N | |
| Drop_priv | enum('N','Y') | NO | | N | |
| Grant_priv | enum('N','Y') | NO | | N | |
| References_priv | enum('N','Y') | NO | | N | |
| Index_priv | enum('N','Y') | NO | | N | |
| Alter_priv | enum('N','Y') | NO | | N | |
| Create_tmp_table_priv | enum('N','Y') | NO | | N | |
| Lock_tables_priv | enum('N','Y') | NO | | N | |
| Create_view_priv | enum('N','Y') | NO | | N | |
| Show_view_priv | enum('N','Y') | NO | | N | |
| Create_routine_priv | enum('N','Y') | NO | | N | |
| Alter_routine_priv | enum('N','Y') | NO | | N | |
| Execute_priv | enum('N','Y') | NO | | N | |
+-----------------------+---------------+------+-----+---------+-------+
19 rows in set (0.01 sec)
mysql>
(3)删除 “host”表
mysql> drop table host;
Query OK, 0 rows affected (0.03 sec)
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| columns_priv |
| db |
| func |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| proc |
| procs_priv |
| tables_priv |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
16 rows in set (0.01 sec)
(4)停止mysql数据库,卸载MYSQL所在分区
[root@localhost ~]# service mysqld stop
[root@localhost ~]# umount /test/
(5)ext3grep分析数据,恢复数据
对mysql执行分区数据扫描
[root@localhost ~]# ext3grep /dev/sdb1 --ls --inode 2
Running ext3grep version 0.10.2
Number of groups: 16
Loading group metadata... done
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340192235 = Wed Jun 20 19:37:15 2012
Number of descriptors in journal: 238; min / max sequence numbers: 18 / 65
Inode is Allocated
Loading sdb1.ext3grep.stage2... done
The first block of the directory is 643.
Inode 2 is directory "".
Directory block 643:
.-- 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 2 d 2 drwxr-xr-x ..
2 3 d 16385 drwxr-xr-x ext3grep
3 4 r 11 rrw-r--r-- ext3grep.txt
4 5 r 12 rrw------- initrd-2.6.18-164.el5.img
5 6 r 13 rrw-r--r-- inode.12
6 7 d 32769 drwx------ lost+found
7 8 r 14 rrw-r--r-- profile
8 9 d 114689 drwx------ mysql
9 10 d 131073 drwx------ test
10 11 r 15 rrw-rw---- ibdata1
11 12 r 16 rrw-rw---- ib_logfile0
12 end r 17 rrw-rw---- ib_logfile1
通过上图可知,mysql目录中有可恢复数据信息,根据查询到的恢复信息,可知mysql目录Inode号是114689 ,接着扫描mysql目录的inode信息。
[root@localhost ~]# ext3grep /dev/sdb1 --ls --inode 114689
Running ext3grep version 0.10.2
Number of groups: 16
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340192235 = Wed Jun 20 19:37:15 2012
Number of descriptors in journal: 238; min / max sequence numbers: 18 / 65
Inode is Allocated
Loading sdb1.ext3grep.stage2... done
The first block of the directory is 253952.
Inode 114689 is directory "ext3grep".
Directory block 253952:
.-- 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 114689 drwx------ .
1 2 d 2 drwxr-xr-x ..
2 end r 114690 rrw-rw---- hosts
注明:在上面的操作中,首先通过“--ls --inode 2” 参数扫描了整个分区信息,查找到mysql目录对应的inode为114689,接着查找inode为114689下面的文件信息。通过对inode为114689的mysql目录进行扫描,查找到了目录下所有文件盒目录的inode信息,根据上面一步操作可知mysql目录的Directory block为253952 下面通过命令查看mysql目录下inode信息。
[root@localhost ~]# ext3grep /dev/sdb1 --ls --block 253952
Running ext3grep version 0.10.2
Number of groups: 16
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340192235 = Wed Jun 20 19:37:15 2012
Number of descriptors in journal: 238; min / max sequence numbers: 18 / 65
Group: 7
Block 253952 is a directory. The block is Unallocated
.-- 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 114689 drwx------ .
1 2 d 2 drwxr-xr-x ..
2 end r 114690 rrw-rw---- hosts
WARNING: inode 114689 was reallocated!
(6)恢复mysql数据文件
[root@localhost ~]# ext3grep /dev/sdb1 --restore-inode 114690
Running ext3grep version 0.10.2
Number of groups: 16
Minimum / maximum journal block: 649 / 8851
Loading journal descriptors... sorting... done
The oldest inode block that is still in the journal, appears to be from 1340192235 = Wed Jun 20 19:37:15 2012
Number of descriptors in journal: 238; min / max sequence numbers: 18 / 65
Restoring inode.114690