EXT3文件系统中误删文件的恢复方法


之前的文章中说明了当用rm -rf误删除文件后的恢复方法,使用这种方法是有前提条件的,必须保证Oracle实例没有关闭,Oracle的相关进程还在运行。而当Oracle进程已经关闭后,就无法再通过利用ora_进程跟踪文件句柄进行恢复了,那么还有办法对误删除的文件进行恢复吗?

rm-rf 误操作的恢复过程

Linux EXT3文件系统下成功恢复误删的文件
 
下面介绍一种用第三方软件进行恢复的方法:
 
--首先确保已经安装了e2fsprogs包
 [root@ora10g ext3grep-0.10.2]# rpm -qa | grep e2fsprogs
 e2fsprogs-1.39-20.el5
 e2fsprogs-devel-1.39-20.el5
 e2fsprogs-libs-1.39-20.el5
 

--软件下载:
 http://ext3grep.googlecode.com/files/ext3grep-0.10.2.tar.gz
 

--用Xshell复制到/opt目录后解压并编译安装
 
[root@ora10g ~]# cd /opt/
 
[root@ora10g opt]# tar -zxvf ext3grep-0.10.2.tar.gz
 

[root@ora10g opt]# ll
 total 500
 drwxr-xr-x 3  1000    1000  4096 Aug 26 09:09 ext3grep-0.10.2
 -rw-r--r-- 1 root  root    236364 Aug 26 09:08 ext3grep-0.10.2.tar.gz
 drwxr-xr-x 3 root  root      4096 Aug 22 16:44 ORCLfmap
 drwxrwxr-x 8 oracle oinstall  4096 Aug 25 11:39 rlwrap-0.37
 -rw-r--r-- 1 root  root    251438 Aug 25 11:37 rlwrap-0.37.tar.gz
 [root@ora10g opt]# cd ext3grep-0.10.2
 [root@ora10g ext3grep-0.10.2]# ./configure&&make&&make install
 编译过程略……
 

--查看软件命令使用方法
 [root@ora10g ext3grep-0.10.2]# ext3grep --help
 Running ext3grep version 0.10.2
 Usage: ext3grep [options] [--] device-file
 Options:
  --version, -[vV]      Print version and exit successfully.
  --help,                Print this help and exit successfully.
  --superblock          Print contents of superblock in addition to the rest.
                          If no action is specified then this option is implied.
  --print                Print content of block or inode, if any.
  --ls                  Print directories with only one line per entry.
                          This option is often needed to turn on filtering.
  --accept filen        Accept 'filen' as a legal filename. Can be used multi-
                          ple times. If you change any --accept you must remove
                          BOTH stage* files!
  --accept-all          Simply accept everything as filename.
  --journal              Show content of journal.
  --show-path-inodes    Show the inode of each directory component in paths.
 Filters:
  --group grp            Only process group 'grp'.
  --directory            Only process directory inodes.
  --after dtime          Only entries deleted on or after 'dtime'.
  --before dtime        Only entries deleted before 'dtime'.
  --deleted              Only show/process deleted entries.
  --allocated            Only show/process allocated inodes/blocks.
  --unallocated          Only show/process unallocated inodes/blocks.
  --reallocated          Do not suppress entries with reallocated inodes.
                          Inodes are considered 'reallocated' if the entry
                          is deleted but the inode is allocated, but also when
                          the file type in the dir entry and the inode are
                          different.
  --zeroed-inodes        Do not suppress entries with zeroed inodes. Linked
                          entries are always shown, regardless of this option.
  --depth depth          Process directories recursively up till a depth
                          of 'depth'.
 Actions:
  --inode-to-block ino  Print the block that contains inode 'ino'.
  --inode ino            Show info on inode 'ino'.
                          If --ls is used and the inode is a directory, then
                          the filters apply to the entries of the directory.
                          If you do not use --ls then --print is implied.
  --block blk            Show info on block 'blk'.
                          If --ls is used and the block is the first block
                          of a directory, then the filters apply to entries
                          of the directory.
                          If you do not use --ls then --print is implied.
  --histogram=[atime|ctime|mtime|dtime|group]
                          Generate a histogram based on the given specs.
                          Using atime, ctime or mtime will change the
                          meaning of --after and --before to those times.
  --journal-block jblk  Show info on journal block 'jblk'.
  --journal-transaction seq
                          Show info on transaction with sequence number 'seq'.
  --dump-names          Write the path of files to stdout.
                          This implies --ls but suppresses it's output.
  --search-start str    Find blocks that start with the fixed string 'str'.
  --search str          Find blocks that contain the fixed string 'str'.
  --search-inode blk    Find inodes that refer to block 'blk'.
  --search-zeroed-inodes Return allocated inode table entries that are zeroed.
  --inode-dirblock-table dir
                          Print a table for directory path 'dir' of directory
                          block numbers found and the inodes used for each file.
  --show-journal-inodes ino
                          Show copies of inode 'ino' still in the journal.
  --restore-inode ino[@seqnr][,ino[@seqnr],...]
                          Restore the file(s) with known inode number 'ino'.
                          The restored files are created in ./RESTORED_FILES/
                          with their inode number as extension (ie, inode.12345).
                          If '@seqnr' is provided then (only) the journal entry
                          with that sequence number is used, otherwise the latest
                          entry is used (if any). You can use that in the case a
                          a file was overwritten or truncated, rather than deleted.
  --restore-file 'path' [--restore-file 'path' ...]
                          Will restore file 'path'. 'path' is relative to the
                          root of the partition and does not start with a '/' (it
                          must be one of the paths returned by --dump-names).
                          The restored directory, file or symbolic link is
                          created in the current directory as 'RESTORED_FILES/path'.
  --restore-all          As --restore-file but attempts to restore everything.
                          The use of --after is highly recommended because the
                          attempt to restore very old files will only result in
                          them being hard linked to a more recently deleted file
                          and as such polute the output.
  --show-hardlinks      Show all inodes that are shared by two or more files.
 

我们看到,还是有很多功能可以用的,这里我们只需用到3个参数:--ls --inode --restore-all 
 
 --开始测试,模拟一个分区/zlm/test1
 [root@ora10g ~]# mkdir /zlm
 [root@ora10g ~]# cd /zlm
 [root@ora10g zlm]# dd  if=/dev/zero  of=test1 bs=8096 count=12800
 12800+0 records in
 12800+0 records out
 103628800 bytes (104 MB) copied, 0.586624 seconds, 177 MB/s
 [root@ora10g zlm]# mkfs.ext3 test1
 mke2fs 1.39 (29-May-2006)
 test1 is not a block special device.
 Proceed anyway? (y,n) y
 Filesystem label=
 OS type: Linux
 Block size=1024 (log=0)
 Fragment size=1024 (log=0)
 25376 inodes, 101200 blocks
 5060 blocks (5.00%) reserved for the super user
 First data block=1
 Maximum filesystem blocks=67371008
 13 block groups
 8192 blocks per group, 8192 fragments per group
 1952 inodes per group
 Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729
 

Writing inode tables: done                           
 Creating journal (4096 blocks): done
 Writing superblocks and filesystem accounting information: done
 

This filesystem will be automatically checked every 27 mounts or
 
180 days, whichever comes first.  Use tune2fs -c or -i to override.
 

 

-- 创建测试目录并挂载
 
[root@ora10g zlm]# mkdir /oradata/ora10g -p
 [root@ora10g zlm]# mount -o loop /zlm/test1 /oradata/ora10g
 [root@ora10g zlm]# df -Th
 Filesystem    Type    Size  Used Avail Use% Mounted on
 /dev/mapper/VolGroup00-LogVol00
              ext3    7.7G  5.6G  1.7G  77% /
 /dev/sda1    ext3    99M  12M  82M  13% /boot
 tmpfs        tmpfs    506M    0  506M  0% /dev/shm
 
/zlm/test1    ext3    96M  5.6M  86M  7% /oradata/ora10g
 

 

--在挂载完的目录/oradata/ora10g中创建测试文件并添加内容
 [root@ora10g ora10g]# touch redo01.log redo02.log redo03.log
 [root@ora10g ora10g]# ll
 total 12
 drwx------ 2 root root 12288 Aug 27 13:59 lost+found
 -rw-r--r-- 1 root root    0 Aug 27 14:11 redo01.log
 -rw-r--r-- 1 root root    0 Aug 27 14:11 redo02.log
 -rw-r--r-- 1 root root    0 Aug 27 14:11 redo03.log
 [root@ora10g ora10g]# cat >> redo01.log << EOF
 > AB
 > EOF
 [root@ora10g ora10g]# cat >> redo02.log << EOF
 > CD
 > EOF
 [root@ora10g ora10g]# cat >> redo03.log << EOF
 > EF
 > EOF
 [root@ora10g ora10g]# ll
 total 15
 drwx------ 2 root root 12288 Aug 27 13:59 lost+found
 -rw-r--r-- 1 root root    3 Aug 27 14:12 redo01.log
 -rw-r--r-- 1 root root    3 Aug 27 14:12 redo02.log
 
-rw-r--r-- 1 root root    3 Aug 27 14:12 redo03.log
 

 

--模拟误操作,删除/oradata/ora10g下所有文件
 [root@ora10g ora10g]# rm -rf *.*
 [root@ora10g ora10g]# ll
 total 12
 drwx------ 2 root root 12288 Aug 27 13:59 lost+found
 [root@ora10g ora10g]# umount /zlm/test1
 umount: /oradata/ora10g: device is busy
 
umount: /oradata/ora10g: device is busy
 

 

由于当前目录是/oradata/ora10g,所以提示"device is busy",退出该目录后再执行
 

 

[root@ora10g ora10g]# cd ~
 [root@ora10g ~]# umount /zlm/test1
 [root@ora10g ~]# df -Th
 Filesystem    Type    Size  Used Avail Use% Mounted on
 /dev/mapper/VolGroup00-LogVol00
              ext3    7.7G  5.6G  1.7G  77% /
 /dev/sda1    ext3    99M  12M  82M  13% /boot
 
tmpfs        tmpfs    506M    0  506M  0% /dev/shm
 

 

--开始扫描/zlm/test1分区中被删除的文件
 [root@ora10g ~]# ext3grep /zlm/test1 --ls --inode 2
 Running ext3grep version 0.10.2
 Number of groups: 13
 Loading group metadata... done
 Minimum / maximum journal block: 519 / 4633
 Loading journal descriptors... sorting... done
 The oldest inode block that is still in the journal, appears to be from 1409119917 = Wed Aug 27 14:11:57 2014
 Number of descriptors in journal: 32; min / max sequence numbers: 2 / 10
 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++
 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:
 Writing analysis so far to 'test1.ext3grep.stage1'. Delete that file if you want to do this stage again.
 Result of stage one:
  2 inodes are referenced by one or more directory blocks, 2 of those inodes are still allocated.
  1 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:
  2 of those inodes could be resolved because they are still allocated.
 All directory inodes are accounted for!
 

 

Writing analysis so far to 'test1.ext3grep.stage2'. Delete that file if you want to do this stage again.
 The first block of the directory is 505.
 Inode 2 is directory "".
 Directory block 505:
          .-- 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  end d      11                                        drwx------  lost+found
    3    4 r      12  D 1409120047 Wed Aug 27 14:14:07 2014  rrw-r--r--  redo01.log
    4    5 r      13  D 1409120047 Wed Aug 27 14:14:07 2014  rrw-r--r--  redo02.log
    5  end r      14  D 1409120047 Wed Aug 27 14:14:07 2014  rrw-r--r--  redo03.log
 

 

[root@ora10g ~]# ll
 total 80
 -rw------- 1 root root  1618 Aug 22 11:19 anaconda-ks.cfg
 drwxr-xr-x 2 root root  4096 Aug 22 12:58 Desktop
 -rw-r--r-- 1 root root 39989 Aug 22 11:19 install.log
 -rw-r--r-- 1 root root  4270 Aug 22 11:19 install.log.syslog
 drwxr-xr-x 3 root root  4096 Aug 27 14:17 RESTORED_FILES
 -rw-r--r-- 1 root root  186 Aug 27 14:16 test1.ext3grep.stage1
 -rw-r--r-- 1 root root  133 Aug 27 14:16 test1.ext3grep.stage2


test1.ext3grep.stage文件是执行命令后生成的,用来存放扫描信息

--把扫描到的已删除文件恢复出来
 
[root@ora10g ~]#  ext3grep  /zlm/test1 --restore-all
 Running ext3grep version 0.10.2
 Number of groups: 13
 Minimum / maximum journal block: 519 / 4633
 Loading journal descriptors... sorting... done
 The oldest inode block that is still in the journal, appears to be from 1409119917 = Wed Aug 27 14:11:57 2014
 Number of descriptors in journal: 32; min / max sequence numbers: 2 / 10
 Writing output to directory RESTORED_FILES/
 Loading test1.ext3grep.stage2... done
 Restoring redo01.log
 Restoring redo02.log
 Restoring redo03.log

注意,在哪个目录执行ext3grep命令恢复文件,就会在该目录中生成一个RESTORED_FILES子目录,下面存放所有恢复出来的文件,并且这个目录下的文件是隐含属性的。

[root@ora10g ~]# ls -la RESTORED_FILES/
 total 28
 drwxr-xr-x  3 root root 4096 Aug 27 14:17 .
 drwxr-x--- 17 root root 4096 Aug 27 14:17 ..
 drwx------  2 root root 4096 Aug 27 13:59 lost+found
 -rw-r--r--  1 root root    3 Aug 27 14:12 redo01.log
 -rw-r--r--  1 root root    3 Aug 27 14:12 redo02.log
 
-rw-r--r--  1 root root    3 Aug 27 14:12 redo03.log

如果不想全部恢复,那么可以使用--resotre-file filename的方式来恢复,前提是你必须知道哪些是你需要恢复的文件

--重新挂载磁盘并确认已经挂载成功
 [root@ora10g ~]# mount -o loop /zlm/test1 /oradata/ora10g
 [root@ora10g ~]# df -Th
 Filesystem    Type    Size  Used Avail Use% Mounted on
 /dev/mapper/VolGroup00-LogVol00
              ext3    7.7G  5.6G  1.7G  77% /
 /dev/sda1    ext3    99M  12M  82M  13% /boot
 tmpfs        tmpfs    506M    0  506M  0% /dev/shm
 /zlm/test1    ext3    96M  5.6M  86M  7% /oradata/ora10g
 

 

--把丢失的文件从RESTORED_FILES中复制到源路径中
 
[root@ora10g ~]# cp RESTORED_FILES/*.log /oradata/ora10g
 [root@ora10g ~]# cd /oradata/ora10g/
 [root@ora10g ora10g]# ll
 total 15
 drwx------ 2 root root 12288 Aug 27 13:59 lost+found
 -rw-r--r-- 1 root root    3 Aug 27 14:21 redo01.log
 -rw-r--r-- 1 root root    3 Aug 27 14:21 redo02.log
 -rw-r--r-- 1 root root    3 Aug 27 14:21 redo03.log

--验证被恢复文件的内容
 
[root@ora10g ora10g]# cat redo01.log redo02.log redo03.log
 AB
 CD
 EF
 [root@ora10g ora10g]#
 

至此,3个文件被完整的恢复了,包括文件内容也都没有丢失。

总结:
 
可以看到,之前模拟在文件系统类型为ext3的/zlm/test1分区下rm -f误删除掉的数据文件都是可以恢复出来的,但前提是删除后没有写入操作,如同我们window中删除磁盘上的数据的原理一样,就算是误格式化了分区,只要没有写入过新的数据,还是能通过Easy Recovery之类的软件对数据进行恢复的。所以,当我们在Linux下误删文件,如果这个文件是挂载在某个分区下的,那么请立即卸载该分区,然后通过以上介绍的方法,对数据进行恢复。不过用这种方法恢复,需要你的数据库文件单独挂在在一个分区下,如果是直接用默认的放在/dev/mapper/VolGroup00-LogVol00,我测试过,是无法恢复出文件的,扫描会失败。

在我的实验中,由于是测试环境,没有单独给数据文件分区,只是默认地安装,测试效果可能与实际环境有很大的区别,这里只是提供数据恢复的一种思路。先用创建了一个文件模拟一个磁盘,如:/zlm/test1并把它格式化成ext3grep的文件系统,ext3grep顾名思义,就是用在对ext3文件系统上进行数据文件恢复的工具,对于ext2、xfs等文件系统而言,它就爱莫能助了。当然,我相信还是能有其他方法或工具可以恢复数据的,这里就暂且不研究了。

所以对于数据库系统而言,极力推荐把数据文件单独挂在在磁盘的分区中,而不是采用默认的磁盘分区,如果要使挂载永久生效,还要修改/etc/fstab文件,加入你要挂载的分区和目录信息。一旦发生误删除,而你的文件系统又恰巧是ext3,而数据库又意外地被关闭了。那么,ext3grep也许就是你最后的机会了!

本文永久更新链接地址:

相关内容