档案删除的回复救援

来源:互联网 发布:淘宝怎么彻底清除缓存 编辑:程序博客网 时间:2024/05/10 06:03

 

今天干了件很蠢的事情~.. 想要将 a电影.srt 改成跟电影.avi 同名字.
于是就下了 mv a电影.srt 电影.avi ... 当按下 enter 时清醒了过来...
发现到那 avi 已经被我清掉了.. srt ... :~
于是就有这篇文章的由来.... ... :~
虽然是写说档案删除的回复救援, 但事实上我没有成功救回来.. XD
主要是因为还要 mount -ro 而且我砍的档案是在 "/". 很麻烦~ :(
而且也并不是那么重要的档案~ 大不了就那影片别看罢了... :p
但是看了这么多~ 来做点小笔记比较好.. 希望未来不会需要用到这篇...
先简单看一下几种常用的 filesystem - Linux日志式文件系统面面观
(
这篇下面有许多相关文件蛮不错的)
 


重点摘要:
主要是下面这三篇文章. 若已经是死连结. 就参考下面转载回来的吧~ :)
 
说明系统rm, mv 等等动作是做何种事情, 流程, 该如何救回来 - UNIX系统被删文件的恢复策略
简易说明实作步骤: Linux文件系统的反删除方法
实作抢救的心得:[chat] 抢救过去!!!! (ext2 undelete)
救援主要就是靠 debugfs 这个程序.
debugfs
的程序就两个 file, 大约共 500 . 有兴趣的就于下处去看看吧~(kernel 2.6.11)
/usr/src/linux/fs/debugfs/

 
以下都是转载自原网站, 怕原网站数据遗失就头痛了~ :(
 


下面这两篇事实上是一样的, 不过怕数据会遗失. 先记起来~ :)
[chat] 抢救过去!!!! (ext2 undelete)
ext2文件系统下恢复误删除的文件
转载上述连结:
 
发信人: thhsieh (居士), 信区: SM
: [Sys] 抢救过去!!!! (ext2 undelete)
发信站: 冷月流苏BBS驿站 (Mon Feb 1 17:21:11 1999) , 转信
本系的 BBS 系统真是多灾多难 ( .... 其实是因为我的疏忽,才会这么多灾
多难 ....) ,继这几日系统时间不正确,造成许多人的 ID 被误砍后,又一次
因系统设定上的问题,将 BBS 的重要备份档给杀了。这件事是学弟发现后告诉
我的,当我上站来一见到他的 mail, 当真是欲哭无泪,差点没去撞墙。那个备
分檔有多重要呢? 这么说吧! 所有等待我们恢复旧信件的使用者数据全在里头。
那时已是周六晚 11:00 左右,我一边想着要编一套说辞向大家解释无法替大家
恢复旧信件与设定了,一边还在想是否能够挽回局面。大家知道, UNIX like
的系统是很难像 M$ 的系统一样,做到 undelete 的,所有网管前辈都曾再三
警告我们,要小心! 小心! 砍档之前三思而后行,砍了之后再后悔也没用。虽
然我已渐渐做到砍档三思而后行,但之次误砍事件是系统在背景中定时执行的,
等到我找出原因时已是档案被砍后一个多小时。
我凭着一点点的印象,想起在网络上,有人讨论过在 Linux ext2 filesystem
undelete 的可能性,但我所见到的多半是负面的答案,但好像真的有人做过
这件事,于是我第一个所做的,就是马上将该档案原来所在的 partition mount
read-only, 禁止任何的写入动作,不是怕再有档案被误砍 (因为已没什么可
砍的了) ,而是怕有新档案写进来,新数据可能会覆盖到旧数据原本存在的扇区
(block)
。我们现在唯一个指望,就是企图将档案原来存在的扇区一个个找回来,
并且「希望」这些扇区上的旧数据都还在,然后将这些扇区串成一个档案。
终于被我找到了!! 原来这方面的技术文件就存在我自己的系统中 :-))
/usr/doc/HOWTO/mini/Ext2fs-Undeletion.gz
于是我就按照这份文件的指示一步步来,总算将一个长达 8MB 的压缩档救回了
99%,
还有一个长达 1.1 MB 的压缩档完整无缺地救了回来。感谢上帝、 Linux
的设计者、写那篇文件的作者、曾经讨论过此技术的人、以及 Linux 如此优秀
ext2 filesystem, 让我有机会抢救过去。现在,我将我的抢救步骤做一个整
理让大家参考,希望有派得上用场的时候 (! 不,最好是希望大家永远不要有
机会用到以下的步数 :-)))
************************************************************************
在此严正声明!! 写这篇文章的目的,是给那些处于万不得已情况下的人们,有
一个挽回的机会,并不意味着从此我们就可以大意,砍档不需要三思。前面提
到,我有一个档案无法 100% 救回,事实上,长达 8MB 的档案能救回 99% 已是
幸运中的幸运,一般的情况下若能救回 70% - 80% 已经要愉笑了。所以,不要
指望 undelete 能救回一切。预防胜于治疗! 请大家平时就养成好习惯,砍档前
请三思!!!
************************************************************************

我们能救回的机会有多大? kernel-2.0.X 系列中 (本站所用的 kernel
2.0.33)
,取决以下两点:
1. 档案原来所在的扇区是否没有被覆写?
2.
档案是否完全连续?
第一点我们可以与时间竞赛,就是当一发现档案误砍时,要以最快的速度 umount
filesystem, 或将该 filesystem remount 成只读。就这次的情况而言,档案
误砍是在事发一个小时后才发现的,但由于该 filesystem 写入的机会很少 (
几乎可确定一天才只有一次,做 backup),所以第一点算是过关了。
第二点真的是要听天由命了,就本站所使用的 kernel, 必须要在假设「长档案」所
占的 block 完全连续的情况下,才有可能完全救回来! 一个 block 1024 bytes,
长达 8 MB 的档案就有超过 8000 block。在经常读写的 filesystem 中,可以
想见长档案很难完全连续,但在我们的系统中,这一点似乎又多了几分指望。同时,
Linux ext2
如此精良的 filesystem, 能做到前 7950 多个 block 都连续,这一点
也功不可没。
好了,以下我就讲一下我的步骤。

1. mount filesystem readonly:
该档案的位置原来是在 /var/hda/backup/home/bbs 下,我们系统的 filesystem
组态是:
root@bbs:/home/ftp/rescue# df
Filesystem 1024-blocks Used Available Capacity Mounted on
/dev/sda1 396500 312769 63250 83% /
/dev/sda3 777410 537633 199615 73% /home
/dev/hda1 199047 36927 151840 20% /var/hda
/dev/hda2 1029023 490998 485710 50% /home/ftp
因此 /var/hda 这个 filesystem 要马上 mount readonly (以下请用 root
):
mount -o remount,ro /var/hda
当然也可以直接 umount 它,但有时候可能有某些 process 正在此 filesystem
下运作,您可能无法直接 umount 它。因此我选择 mount readonly。但您也可以
:
fuser -v -m /usr
看一下目前是那些 process 在用这个 filesystem, 然后一一砍掉,再 umount

2.
执行
echo lsdel | debugfs /dev/hda1 | less
看一下该 filesystem 最近被砍的 inode (档案) 有那些 (为什么是 /dev/hda1?
请见上头的 df 列表)? 在这里要说一下,在 UNIX like 的系统中,所有的档案都
有一个 inode 指向它, inode 中记录了档案的重要信息,如大小、时间、属性等
等。就我们的系统而言,其列示如下:
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

请注意! inode 里头不会记录档案的文件名,文件名是记录在该档案所在的目录的
data block
中,故在此我们见不到。因此,我们必须要在档案大小、被砍时间
等信息中判断出要救回的档案是那一个。在此,我们要救回 29773 这个 inode

3.
执行
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 才对啊!
在这里要谈一下 UNIX like filesystem 的「奥密」了。上头所列的前 12 block
是真正指到档案数据的 block, 称之为 direct block 。第 13 个称为第一阶
indirect block,
14 个称为第二阶 indirect block 。什么意思? 该文件的资料
所在的 block 位置如下:
123134
123136
123137
123138
......
131409
131410
131411 =========> 131412
131413
131414 (
第一阶,共 256 )
......
131667
131668 =========> 131669 ==========> 131670
131671
131672 (
256 )
......
131925
131926 ==========> 131927
131928
131929 (
256 )
......
132182
132183 ==========> 132184
132185 (
256 )
......
各位明白吗? 13 (131411) 与第 14 block 其实不是 data, 而是 index,
它指出接下来的 block 的位置。由于一个 block 的大小是 1024 bytes, 一个 int
32 位系统中是 4 bytes, 故一个 block 可以记录 256 笔数据。以 131411
block
为例,它所记录的数据即为 (在档案未砍前):
131412 131413 131414 .... 131667 ( 256 )
而这 256 block 就真正记录了档案数据,所以我们称为第一阶。同理,第二阶
就有两个层 index, 131668 来说,它可能记录了:
131669 131926 132182 .... (最多有 256 )
131669 block 记录为:
131670 131671 131672 .... 131925 ( 256 )
而这 256 block 才是真正储存档案数据的。而我们要的,就是这些真正储存档
案资料的 block
理论上,我们只要将这些 index block 的内容全部读出来,然后照这些 index
所有的 block 全部读到手,就能 100% 救回档案 (假设这些 block 全部没有被新
档案覆写的话)。工程很大,但是可行。不幸的是,在 kernel-2.0.33, 其设计是,
如果该档案被砍了,则这些 index block 全部会规零,因此我所读到的是
0 0 0 0 0 ..... ( 256 )
! 没办法知道这些 data block 真正所在的位置。所以,在此我们做了一个很大
的假设: 整个档案所在的 block 是连续的! 也就是我上头的例子。这也就是为什
么说,只有连续 block (是指后头的 indirect block) 的档案才能完整救回,而
这一点就要听天由命了。

4.
好了,现在我们只好假设所有的档案处于连续的 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。对于第二阶 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, ....)
了。

5.
最后一步,就是把档案「剪」出来,并看看我们救回多少了。在这里我们可以用
split
这个工具,假设我们重复上述步骤,弄出来的 recover 档大小为 8294400,
而我们要的大小是 8220922, 那就这样下指令:
split -b 8220922 recover 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 设计者正着手研究,看能否克服这个困难,也就是在档案砍掉时,不要
index block 规零。我刚刚试一下 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 157
642 157643 157644 157645 157646 157647 157648 157649 157650 157651 157652 157653
157654 157655 157656 157657 157658 157659 157660 157661 157662 157663 157664 15
7665 157666 157667 157668 157669 157670 157671 157672 157673 157674 157675 15767
6 157677 157678 157679 157680 157681 157682 157683 157684 157685 157686 157687 1
............................................................................
9745 159746 159747 159748 159749 159750 159751 159752 159753 159754 159755 15975
6
TOTAL: 2126
真是太完美了!! 这意味着在 kernel-2.2.X 的环境下,我们不必假设所有的 block
连续,而且可以百分之百找回所有砍掉的 block! 因此上述的第二个风险就不存在了。
以上数据,谨供参考。
参考文件: Ext2fs-Undeletion Mini HOWTO

 
 


UNIX系统被删文件的恢复策略
以下转载自上述连结:
蓝森林 http://www.lslnet.com 2001117 20:19
作者: 李贵林陈朝晖
DOS/Windows不同,UNIX文件被删除后很难恢复,这是由UNIX独特的文件系统结构决定的。UNIX文件目录不像 DOS/Windows那样,文件即使被删除之后仍保存有完整的文件名、文件长度、始簇号(即文件占有的第一个磁盘块号)等重要信息;相反,它的文件信息全部依靠一种被称为i节点的数据结构来描述,而i节点在相应文件被删除之后即被清空,因此,要想直接恢复被删除的文件内容几乎是不可能的,必须另辟蹊径。本文结合实际,讨论几种文件恢复策略及其关键步骤的具体实现。
  一、UNIX文件系统结构
  我们知道,UNIX是以文件卷作为其文件系统存储格式的,而不同的UNIX系统,文件卷格式是有差异的,甚至即使是同一UNIX操作系统的不同版本,其文件系统未必完全相同,例如:SCO UNIX 4.1版与5.0版文件系统结构就有明显差异,但只要是UNIX系统,其文件卷的基本结构是一致的。分析如下:
  不管是什么UNIX系统,不管什么版本,其文件卷至少包括引导块、超级块、i节点表、数据区等几个部分。除此之外,不同UNIX版本可能还有不同的差异。例如:SCO UNIX系统的位图索引块和位图块AIX的逻辑卷表等。这些系统的特殊性不影响下文的恢复策略,故这里不作讨论,仅介绍标准UNIX文件卷结构。
 
 1. 引导块
  位于文件卷最开始的第一扇区,这512字节是文件系统的引导代码,为根文件系统所特有,其它文件系统这512字节为空。
  2. 超级块
  位于文件系统第二扇区,紧跟引导块之后,用于描述本文件系统的结构。如i节点长度、文件系统大小等,其结构存放于/usr/include/sys/filsys.h中,其结构如下:
  struct filsys
  {
  ushort s_isize; /*磁盘索引节点区所占用的数据块数*/
  daddr_t s_fsize; /*整个文件系统的数据块数*/
  short s_nfree; /*在空闲块登录表中当前登记的空闲块数目*/
  daddr_t s_free[NICFREE]; /*空闲块登记表*/
  short s_ninode; /*空闲索引节点数*/
  ino_t s_inode[NICINOD]; /*空闲节点登记表*/
  char s_flock; /*加锁标志位*/
  char s_ilock; /*节点加锁标志位*/
  char s_fmod; /*超级块修改标志*/
  char s_ronly; /*文件系统只读标志*/
  time_t s_time; /*超级块上次修改的时间*/
  short s_dinfo[4]; /*设备信息*/
  daddr_t s_tfree; /*空闲块总数*/
  ino_t s_tinode; /*空闲节点总数*/
  char s_fname[6]; /*文件系统名称*/
  char s_fpack[6];
  long s_fill[13]; /*填空位*/
  long s_magic; /*指示文件系统的幻数*/
  long s_type; /*新文件系统类型*/
  };
  3. i节点表
  i节点表存放在超级块之后,其长度是由超级块中的s_isize字段决定的,其作用是用来描述文件的属性、长度、属主、属组、数据块表等,其数据结构在/usr/include/sys/ino.h中,如下:
  struct dinode
  {
  ushort di_mode;
  short di_nlink;
  ushort di_uid;
  ushort di_gid;
  off_t di_size;
  char di_addr[40];
  time_t di_atime;
  time_t di_mtime;
  time_t di_ctime;
  };
  4. 目录结构
  UNIX所有文件均存放于目录中,目录本身也是一个文件。目录存放文件的机制如下:首先,目录文件本身也象普通文件一样,占用一个索引节点,其次,由这个索引节点得到目录内容的存放位置,再次,从其内容中取出一个个的文件名和它对应的节点号,从而访问一个文件。目录结构如下:
  索引节点号(2字节) .(本目录)(14字节)
  索引节点号(2字节) ..(父目录)(14字节)
  索引节点号(2字节) 文件名(14字节)
  索引节点号(2字节) 文件名(14字节)
  索引节点号(2字节) 文件名(14字节)
  由上可知文件名是依靠目录来描述的,文件的内容和其它信息则由索引节点来描述。
  二、文件的删除过程
  UNIX下删除一个文件的过程很简单,那就是释放索引节点表和文件占用的数据块,清空文件占用的索引节点,但不清除文件内容。但删除文件与删除目录的处理不尽相同,不同命令删除文件的过程也不相同。
  1. 删除一个文件
  UNIX 删除一个文件的具体步骤是:根据文件i节点的地址表逐一释放文件占用的磁盘数据块,然后清空相应的节点,最后释放i节点。
  2. 删除一个目录
  删除一个目录的过程:首先逐一删除目录里的所有文件,然后删除目录。目录本身也是一个文件,故删除方法与删除文件一致。
  3. 几种不同的删除命令
  .rm 命令
  一般删除命令,删除过程上述已说明。
  .mv命令
  格式:mv 文件1 文件2
  处理过程是将文件2的数据块释放,然后将文件1的名称改为文件2,再释放文件2所占的i节点。
  . > 命令
  格式:>文件名
  若产生一个新文件,>命令仅仅申请一个i节点,而不写入任何文件内容;若清空一个已经存在的文件,则释放文件所占的数据块,并将文件长度清零。
  三、被删文件的恢复策略
  要恢复被删除的文件,只能根据删除后留下的东西去做文章。文件被删除后留下了什么呢?由上述分析可知:其一、留下了文件的内容;其二、留下了现场。文件的恢复策略只能从这两个方面来分析。以下谈几种恢复策略。
  1.根据磁盘现场进行恢复
  如果文件被删除,现场未被破坏(即文件被删除后硬盘未发生过写操作),而且假定只删除了一个文件,那么可根据系统的分配算法进行恢复。因为系统建立一个文件时,必定根据某一特定的分配算法决定文件占用的数据块位置。而当该文件被删除后,它所占用的数据块被释放,又回到系统的分配表中,这时如果重新建立一个文件,系统根据原来的分配算法分配出的数据块必定跟该文件原来占用的数据块一致,而且我们知道,UNIX文件最后一数据块尾部多出的字节是全部置0的,据此只要调用系统的数据分配算法,在系统中一块块的申请数据块,因为UNIX文件最后一个数据块尾部多出的字节全部为0,所以,只要发现一个分配出的数据块中尾部全为0,即可认为文件结束,由此可确定文件长度和内容,进而实现恢复。方法如下:
  申请一个索引节点,即向系统申请创建一个新文件名而不写入任何内容。如:#>/tmp/xx
  调用系统分配数据块算法getnextfreeblock()得到一个数据块号,记入某一地址表变量中。
  读出这个数据块,判断其尾部是否全部连续为0,若不是,则回到(2),若是,则进行(4)
  首先用系统函数fstat得到/tmp/xxi节点号,然后将(2)步所得的地址表写入索引节点的地址表中(注意间址问题),并根据数据块个数和最后一块中有效数据长度计算出文件大小,写入i节点的di_size字段。
  回写系统的索引节点表即可。
  需要说明的是,第一,系统分配数据块的算法因不同的UNIX版本而不同;第二,有的UNIXSCO UNIX 5.0版,其空闲数据块的分配和回收是使用一种动态链表的数据结构来实现的,它们的文件恢复更加容易,只要在空闲链表中的表尾去寻找即可,笔者另行描述。
  2. 根据内容恢复。
  若现场已被破坏,即硬盘发生过写操作,那么只好根据内容来恢复。而且,由于UNIX是一个多进程、多用户系统,它每一次开关机或硬件、通讯故障等都会记录系统日志、.sh_history等,硬盘现场被破坏可能性极大。因此讨论按内容恢复的方法具有更大的实用价值。笔者经过实际探索得出下列四种恢复策略供参考。
  关键字搜索法
  如果知道被删除的文件内容中若干字节的内容,而且该文件长度又不超过一个磁盘块,那么可以在整个文件系统中搜索这一字节串,得出一个文件所在的数据块,将它们的块号填入一个i节点,即可恢复一个文件,搜索文件系统的算法很简单,说明如下:
  a. #df -k 确定文件系统的设备文件名(/dev/root)
  b.用下述函数搜索,若成功,返回数据块号,反之返回-1。其中fsname是文件系统的设备名,如/dev/rootcomp()参数是实现搜索条件的函数。
  long searchfs(char *fsname , int comp())
  {
  FILE *fp;
  char buf[1024];
  long i=0;
  fp=fopen(fsname,"r");
  while (!feof(fp))
  {
  fread(buf,1024,1,fp);
  if (comp()) /* 检查是否符合搜索条件 */
  return i; /* 若成功返回块号 */
  i++;
  }
  fclose(fp);
  return -1; /* 未找到符合条件的块,返回-1*/
  }
  精确长度搜索法
  如果知道被删除文件的精确长度(字节数),那么可根据一个数据块的大小,计算出文件的最后一个数据块中数据的精确长度,该数据块中其它字节必然是全0。根据这一条件,通过搜索整个文件系统,找出其中符合条件的数据块,若出现多个块符合要求,则还需要根据其它条件区分。但不管怎样,根据精确长度分析也是恢复数据的一个策略。
  内容关联法
  如果知道文件内容中存在某种可实现的关联,例如文件的校验和,或者文件内容的某种上下文关系,那么也可通过搜索整个文件系统,通过反复尝试寻找符合关联条件的磁盘数据块,进而恢复一个文件。
  环境比较法
  如果知道删除文件所在的文件系统的安装过程,那么,另行找一台完全相的机器,按原来完全相同的步骤安装相同版本的UNIX和相应的其它软件,可以想象,新的机器环境会与原来的环境基本相同,比较两个机器上相同文件系统的内容,可以推断出被删除文件的大致位置,至少可以大大减少查找的范围,一旦查找的范围足够小时,可以用逐个观察和尝试的方法结合其它条件恢复数据,降低恢复的难度,增加恢复的可靠性。
  UNIX系统下文件系统恢复的具体实现依赖于不同操作系统和不同版本的具体文件系统结构和磁盘块分配算法。本文试图总结出一种一般性的思路和策略,限于篇幅,不能详细讨论它们的具体实现过程。
摘自:http://linux.softhouse.com.cn

 
 


Linux文件系统的反删除方法
以下转载自上述连结:
 
Linux文件系统的反删除方法
  作为一个多用户、多任务的操作系统,Linux下的文件一旦被删除,是难以恢复的。尽管删除命令只是在档节点中作删除标记,并不真正清除文件内容,但是其它用户和一些有写盘动作的进程会很快覆盖这些数据。不过,对于家庭单机使用的Linux,或者误删档后及时补救,还是可以恢复的。
1Ext2文件系统结构的简单介绍
  在Linux所用的Ext2文件系统中,文件是以块为单位存储的,默认情况下每个块的大小是1K,不同的块以块号区分。每个档还有一个节点,节点中包含有档所有者,读写权限,文件类型等信息。对于一个小于12个块的档,在节点中直接存储档数据块的块号。如果档大于12个块,那么节点在12个块号之后存储一个间接块的块号,在这个间接块号所对应的块中,存储有256个档数据块的块号(Ext2fs中每个块号占用4字节,这样一个块中所能存储的块号就是 1024/4=256)。如果有更大的档,那么还会在节点中出现二级间接块和三级间接块。
2。恢复被误删档的方法
  大多数Linux发行版都提供一个debugfs工具,可以用来对Ext2文件系统进行编辑操作。不过在使用这个工具之前,还有一些工作要做。
  首先以只读方式重新挂载被误删的档所在分区。使用如下命令:(假设文件在/usr分区)
mount –r –n –o remount /usr
-r表示只读方式挂载;-n表示不写入/etc/mtab,如果是恢复/etc上的档,就加上这个参数。如果系统说xxx partion busy,可以用fuser命令查看一下是哪些进程使用这个分区上的档:
fuser –v –m /usr
如果没有什么重要的进程,用以下命令停掉它们:
fuser -k –v –m /usr
然后就可以重新挂载这些文件系统了。
  如果是把所有的档统一安装在一个大的/分区当中,可以在boot提示符下用linux single进入单用户模式,尽量减少系统进程向硬盘写入数据的机会,要不干脆把硬盘挂在别的机器上。另外,恢复出来的数据不要写到/上面,避免破坏那些有用的数据。如果机器上有dos/windows,可以写到这些分区上面:
mount –r –n /dev/hda1 /mnt/had
然后就可以执行debugfs:(假设Linux /dev/hda5
#debugfs /dev/hda5
就会出现debugfs提示符debugfs
使用lsdel命令可以列出很多被删除的文件的信息:
debugfslsdel
debugfs: 2692 deleted inodes found.
Inode Owner Mode Size Blocks Time deleted
164821 0 100600 8192 1/ 1 Sun May 13 19:22:46 2001
…………………………………………………………………………………
36137 0 100644 4 1/ 1 Tue Apr 24 10:11:15 2001
196829 0 100644 149500 38/ 38 Mon May 27 13:52:04 2001
debugfs:
  列出的档有很多(这里找到2692个),第一字段是档节点号,第二字段是档所有者,第三字段是读写权限,接下来是档大小,占用块数,删除时间。然后就可以根据档大小和删除日期判断那些是我们需要的。比如我们要恢复节点是
196829的文件:
可以先看看文件数据状态:
debugfsstat <196829>
Inode: 196829 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 0 Group: 0 Size: 149500
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 38
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 2001
atime: 0x31a21dd1 -- Tue May 21 20:47:29 2001
mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 2001
dtime: 0x31a9a574 -- Mon May 27 13:52:04 2001
BLOCKS:
594810 594811 594814 594815 594816 594817
………………………………….
TOTAL: 38
然后就可以用dump指令恢复文件:
debugfsdump <196829> /mnt/hda/01.sav
这样就把档恢复出来了。退出debugfs
debugfsquit
另一种方法是手工编辑inode
debugfsmi <196829>
Mode [0100644]
User ID [0]
Group ID [0]
Size [149500]
Creation time [0x31a9a574]
Modification time [0x31a9a574]
Access time [0x31a21dd1]
Deletion time [0x31a9a574] 0
Link count [0] 1
Block count [38]
File flags [0x0]
Reserved1 [0]
File acl [0]
Directory acl [0]
Fragment address [0]
Fragment number [0]
Fragment size [0]
Direct Block #0 [594810]
…………………………….
Triple Indirect Block [0]
使用mi指令后每次显示一行信息以供编辑,其它行可以直接按回车表示确认,把deletion time改成0(未删除),Link count改成1。改好后退出debugfs
debugfsquit
然后用fsck检查/dev/hda5
fsck /dev/hda5
程序会说找到丢失的数据块,放在lost+found里面。这个目录里的文件就是我们要的东东。
Now all O.K. Good Luck.

 
EXT3 Recovery - Score one for the fleshlings


以下转载自上述连结:
修复ext3文件系统的超级块
I just got my blog back after wrestling with a hosed ext3 partition, and winning. Long story short, I put some bad ram into Adrock which quickly caused a kernel panic. Upon removing the bad RAM and rebooting /var was toast, the journal was toast and it looked like the superblocks were a bit charred as well. I had to dig for a while to get this problem solved... so here's the info on the failure and the fix.
 
/var was unmountable.
I removed /var from fstab and booted the machine on a /var dir off the root so I could work on it remotely.
Here's what happened next. I fsck a variety of ways, fsck.ext3 etc.. each reported the same:
fsck /dev/ida/c0d0p7
fsck 1.27 (8-Mar-2002)
e2fsck 1.27 (8-Mar-2002)
Group descriptors look bad... trying backup blocks...
fsck.ext2: Invalid argument while checking ext3 journal for /var
Tried downgrading to ext2 to bypass the hosed journal issues:
tune2fs -O ^has_journal /dev/ida/c0d0p7
tune2fs 1.27 (8-Mar-2002)
tune2fs: Invalid argument while reading journal inode
No good. Tried mounting as ext2 read only:
mount -t ext2 /dev/ida/c0d0p7 /mnt -o ro
mount: wrong fs type, bad option, bad superblock on /dev/ida/c0d0p7,
or too many mounted file systems
Nada. Tried some more stuff... tune2fs, and debugfs to try to fix / disable the journal, then decided I'd better back up the partition... should have done that first! ;P
e2fsck -c /dev/ida/c0d0p7
e2fsck 1.27 (8-Mar-2002)
Group descriptors look bad... trying backup blocks...
e2fsck: Invalid argument while checking ext3 journal for /var
[root@adrock init.d]# tune2fs -j /dev/ida/c0d0p7
tune2fs 1.27 (8-Mar-2002)
The filesystem already has a journal.
[root@adrock init.d]# debugfs -w /dev/ida/c0d0p7
debugfs 1.27 (8-Mar-2002)
/dev/ida/c0d0p7: Can't read an inode bitmap while reading inode bitmap
debugfs: quit
[root@adrock init.d]# dd if=/dev/ida/c0d0p7 of=/big/var.bak.dd
530368+0 records in
Still hosed, but now I have a backup of the burnination. And now for the FIX!!!
mke2fs -S /dev/ida/c0d0p7
mke2fs 1.27 (8-Mar-2002)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
66528 inodes, 265184 blocks
13259 blocks (5.00%) reserved for the super user
First data block=1
33 block groups
8192 blocks per group, 8192 fragments per group
2016 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185
Writing superblocks and filesystem accounting information: done
That did it! mke2fs re-wrote all of the superblocks and group descriptors and I was able to mount in RO mode and copy off the data. After that I was able to fsck and remount the original parition with no problems!
I found some great info on the RedHat ext3 mailing list archive which led me to this fix. Big thanks to the guys on that list!

 

以下两页的说明, 一页说有支持 ext3, 一页说没有 :(
DEBUGFS
debugfs(8) - Linux man page
 


debugfs
的程序就两个 file, 大约共 500 . 有兴趣的就于下处去看看吧~(kernel 2.6.11)
/usr/src/linux/fs/debugfs/
Kernel v2.6.11.6-bk3 fs/debugfs/
LinuxHQ - Documentation
 
恢复ext2文件系统中的被删除文件

作者:作者
如果你不小心误删除了一个重要的文件,如rm -rf kkk ,kkk是你的一个非常重要的文件,你肯定非常痛苦,这时你千万不能惊慌,应该马上停止向你的硬盘写入任何文件。它完全是可以恢复的。(我这里专门针对ext2文件系统写了如下的内容,其它的文件系统也有办法,我以后在写)
#debugfs /dev/hda1(
被删除文件所在的分区)
debugfs:lsdel
就可列出你最近被删除文件的inode表,大致如下:
Inode Owner Mode Size Blocks Time deleted
依此是节点表号,属主,文件属性(即读、写等),大小,block(一般1block=1K),被删除时的时间。有了这些信息,你应该能很快就判断出那个文件是你想恢复的。这时用
debugfs:dump &lt;
你想恢复的inode表值&gt; /home/directory(到那个目录)
OK
!就这么简单,/home/directory中可以找到它。
当然,如果你的文件很多,这样做一个一个的肯定很麻烦,你可以下载一些工具。我这里给个地址:
http://revocer.sourceforge.net/linux/recover

各位,去试试吧,有什么困难可以根我联系。

多谢老兄,这是弟兄们最想要的。
兄弟在实践过程中,出现这样的信息,不知道如何处理。请老兄指教。
311543 0 100600 7603556 14/ 14 Wed Oct 2 18:39:21 2002
586046 0 100644 7044 2/ 2 Wed Oct 2 18:51:50 2002
760593 0 100600 363 1/ 1 Wed Oct 2 18:53:35 2002
9551 deleted inodes found.
debugfs: dump 311543
dump: Usage: dump_inode [-p] &lt;file&gt; &lt;output_file&gt;
debugfs: dump 311543 /root
311543: File not found by ext2_lookup
debugfs:
兄弟想恢复311543这个,因为我是在/root目录下删除了一个文件,我看了就是311543这个,但用下面命令恢复,就出现了如上的提示,不知如何下手。请老兄助兄弟一力。

你应该这样的.

debugfs:dump &lt;311543&gt; /root/ppp(
随便什么文件名).
你再试试.

成功了没?

我现在在windows,而我的linuxJFS.恢复比较方便.等会我切到LINUX再建一个ext2系统,我以前试过,应该肯定是可以的.



老兄厉害,服了,一下就OK了。。。。
现在兄弟有一个疑问:我删除的是一个.tar.gz文件,但恢复完成后,却不能用
#tar zxvf *tar.gz
来解压了。
另外就是如何才能恢复成原来那样的文件名,比如我删除的是wine.tar.gz,但事先我记不得这个具体的文件名是什么的了,但我还想恢复成原来的文件名,比如我删除了系统中重要的文件,但我又不记得它是什么样的文件名了,但这个文件名对系统来说又是极为重要的,比如/usr/bin下的mozilla。我该如何做呢??

哈哈。这个也好办。

主要是要知道原因。先回答简单的。要知道文件名用:
debugfs:ls -d
就可以了。
至于文件不能用,是因为dump下来的是连续块,而你的文件可能不是连续块。
debugfs:stat &lt;inode&gt;可以看它的状态,原后将他们一一dd下来(当然有工具可以省不少力气)
算了,我还是写一个详细的教程吧。(大家不要心急啊。过几天见,国庆我可是导游啊!)



多谢老兄,祝老兄节日快乐
其实做到这一步,兄弟已经感动万分了。因为兄弟通过老兄的教程看到了linux系统出了意外事故也是能应对的。不能应对,说明兄弟的技术水平不行。还得请老兄多多指教。
期待中,但不急。。。。

北南致意!

今天游了一天的西湖。

明天还要去。只有晚上空一点。
我发现e2fsprogs1.29版的比较好用,用它来恢复文件较好,建议升级。另外,使用工具的话,建议使用mc, 下载地址为 http://www.gnome.org/projects/mc/ .今天我用google搜索了一下(关键词 rm linux recover how ),发现网上的教程其实很多。缺少的是一些原理的分析部分(其实学过汇编及unix系统的兄弟应该很清楚才对),我过几天就补充讲一下。

wxz8
兄数据恢复方法操作图,本图由wxz8兄提供。请弟兄们多多实践,有问题,请跟帖。



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=666232
 
原创粉丝点击