浅谈
Linux文件
系统反删除方法
$ i; R5 }$ |" w& K/ c, ?9 I2006-06-01
0 V" ^ I1 H1 V1 G; z i& M
: k5 k: y# `! ]2 y) Q3 `
7 L5 S+ Q% q7 f. a8 a9 z1 ^/ O3 w! S8 l# ?/ m
作为一个多用户、多任务的
操作系统,Linux下的文件一旦被删除,是难以恢复的。尽管删除命令只是在档节点中作删除标记,并不真正清除文件内容,但是其它用户和一些有写盘
动作的进程会很快覆盖这些资料。不过,对于家庭单机使用的Linux,或者误删档后及时补救,还是可以恢复的。
/ l! ]# x# j$ Q' k) X( M
# C9 @+ C; @1 i( N; p- u 1、Ext2文件系统
结构的简单介绍
, A, K; j& M9 n) s- J2 r) y9 s' c% o9 B0 ]) S
在Linux所用的Ext2文件系统中,文件是以块为单位存储的,默认情况下每个块的大小是1K,不同的块以块号区分。每个档还有一个节点,节点中包含有档所有者,读写权限,文件
类型等
信息。对于一个小于12个块的档,在节点中直接存储档
数据块的块号。如果档大于12个块,那么节点在12个块号之后存储一个间接块的块号,在这个间接块号所对应的块中,存储有256个档
数据块的块号(Ext2fs中每个块号占用4字节,这样一个块中所能存储的块号就是1024/4=256)。如果有更大的档,那么还会在节点中出现二级间接块和三级间接块。
. F- q% d: d- P8 B( B6 T8 ^6 W' n
5 Q$ M6 D1 T( R3 t 2、恢复被误删档的方法
, c* `0 e- F1 i! M! j9 Y* @
/ T( I8 I9 ^8 B4 {& |7 C- R( u' T" R 大多数Linux发行版都提供一个debugfs工具,可以用来对Ext2文件系统进行
编辑操作。不过在使用这个工具之前,还有一些工作要做。
3 g0 I7 h5 Y- I. L W9 x* F( f
" E1 H: v! q' h% u8 r. Z 首先以只读方式重新挂载被误删的档所在分区。使用如下命令:(假设文件在/usr分区)
6 g2 X% j: c6 h1 P& u2 ~ h& ]9 T
" X; k/ S' m. U6 J- b# l mount?Cr?Cn?Coremount/usr
! N7 V/ k$ j/ ^# p; v8 ~% I3 T
" A; E: ~# u2 H4 R Y' u -r表示只读方式挂载;-n表示不写入/etc/mtab,如果是恢复/etc上的档,就加上这个参数。如果系统说xxxpartionbusy,可以用fuser命令查看一下是哪些进程使用这个分区上的?n:
; D# y0 j4 V* L. i- ~; S: b% d
; z, D0 L6 K- l6 `0 A. R fuser?Cv?Cm/usr
" R3 ^/ W% F& V7 ~
- O5 H9 z4 g8 _0 c+ Z' @% r2 f5 I9 y 如果没有什么重要的进程,用以下命令停掉它们:
/ v6 A" |8 ~6 H* i
" L. v) n, w- x2 @6 ` fuser-k?Cv?Cm/usr
( p: Z" [" W5 \
0 @" p. ^7 u" \- u 然后就可以重新挂载这些文件系统了。
9 g8 r" f- ^! d! l" c2 G Q6 J; N8 B) W) I8 o
如果是把所有的档统一安装在一个大的/分区当中,可以在boot提示符下用Linuxsingle进入单用户模式,尽量减少系统进程向
硬盘写入资料的机会,要不干脆把硬盘挂在别的
机器上。另外,恢复出来的资料不要写到/上面,避免破坏那些有用的资料。如果
机器上有dos/
windows,可以写到这些分区上面:
$ H5 l& z4 \" t+ O
0 d( n, Z$ }& y& m6 I mount?Cr?Cn/dev/hda1/mnt/had
4 W1 ^! P. B5 r5 }
0 {. B8 R! J' X
然后就可以执行debugfs:(假设Linux在/dev/hda5)
1 @ U, I- D: H; G; n( J/ F' l, C' Q% l0 s
#debugfs/dev/hda5
+ ~: j: S$ G* u" ?1 K
4 r( }- J' t( n 就会出现debugfs提示符debugfs:
~ s2 e8 `# V7 J( y3 d' n! ?
! D" `9 ?, |, b. L, \! M
使用lsdel命令可以列出很多被删除的文件的信息:
; J' M! S; y5 r( w7 y2 `5 {6 k6 {5 d1 q/ ^( A& ?1 [$ `
debugfs:lsdel
% P" m! o. T* A5 C6 T* {
& T8 }( B% R$ e& O5 ?
debugfs:2692deletedinodesfound.
4 I L2 ]! @. X* A( D6 Y5 U* W$ m0 y% U( L7 i+ e. n" ]7 N
InodeOwnerModeSizeBlocksTimedeleted
* a& L( Q2 b7 @$ l7 z3 h
# _, |7 m! u$ U. {' q8 o
164821010060081921/1SunMay1319:22:462001…………………………………………………………………………………
6 J9 A: T/ w0 f0 {8 h$ k6 Z1 @# [) M! Z( l. u( g( Q
36137010064441/1TueApr2410:11:152001
: X- ]3 t) S) Y# i( n
; a+ F# @1 ^3 j 196829010064414950038/38MonMay2713:52:042001
: S. ~! U1 S, Q& Y
/ f/ O# m d; a' d( s E
debugfs:
5 x* e8 R" J6 {+ \; b% R, m, a. m7 u
列出的档有很多(这里找到2692个),第一字段是档节点号,第二字段是档所有者,第三字段是读写权限,接下来是档大小,占用块数,删除
时间。然后就可以根据档大小和删除日期判断那些是我们需要的。比如我们要恢复节点是196829的文件:
2 i9 j, [; x. _' k# j) ~
9 w0 Y1 v' E6 K& h+ p( t
可以先看看文件资料状态:
; B" o& o4 s k9 h
$ h" y, s( ?* l) L
debugfs:stat%26lt;196829%26gt;
' l, z( l( a/ K p5 r
9 V' q3 W' l8 l' o Inode:196829Type:regularMode:0644Flags:0x0Version:1
: g# v9 ~9 O9 o2 V9 C- }
/ E* j" E8 }( C$ a1 W
User:0Group:0Size:149500
( I, j8 @' c: h( |9 B
( i: Y' K0 p# V1 K
FileACL:0DirectoryACL:0
+ d0 ~, k; s4 L: t1 v& d% R2 T7 Q9 q9 I" b* ?
Links:0Blockcount:38
7 n" i1 j6 Y }- C
: c3 j/ J _ @) ^% ?5 D2 Y
Fragment:Address:0Number:0Size:0
! t9 H5 _5 F1 I
% j' u7 Q- n3 x& ?/ ]: l5 q- t: K
ctime:0x31a9a574--MonMay2713:52:042001
# u* s' u( X. ]4 o* t' O
, P6 X* {% t$ H# }2 I$ u atime:0x31a21dd1--TueMay2120:47:292001
$ e# T% R: m% _$ K( _; S/ T$ j9 H+ L. f7 L1 ?' L
mtime:0x313bf4d7--TueMar508:01:272001
$ @: F3 ^: o0 |# {; M# V6 J" D% z" A! B3 _" M! x) Q5 C2 u
dtime:0x31a9a574--MonMay2713:52:042001
6 Z: A- s2 T5 o
9 r$ g: b$ O: I BLOCKS:
% t4 P$ o2 ?- Z6 V, a% n* Z" X8 T, `1 @! X" V
594810594811594814594815594816594817
2 j, w( o1 f* D' ?6 @! I4 W7 B' m6 M6 j; @4 c. i E3 Q- b+ Y( Y
………………………………….
2 p! N ]' | R5 J" ^4 Y: T, h. T/ ^+ d+ B; ~) B |3 J
TOTAL:38
& d2 |2 F; n6 c- [$ T
& E9 u2 P5 E( B/ u 然后就可以用dump指令恢复文件:
$ q! m* d) P6 ]0 V0 e& @" R6 V
[# ^/ w. T) p" n8 v2 M4 C debugfs:dump%26lt;196829%26gt;/mnt/hda/01.sav
3 b4 X' K4 e" M/ a0 |# @3 s8 C, }: `7 A3 s2 O
这样就把档恢复出来了。退出debugfs:
8 ~3 l' e1 `- g1 L" |/ [8 l$ Y
* ]) S2 B, D" ]5 f$ Y5 f debugfs:quit
$ C# k: W- O, V5 A" O6 E3 e
6 x2 E8 v* d3 @2 @' Z 另一种方法是手工编辑inode:
7 @1 A6 U8 q1 P4 y5 M
# B. O) }6 r/ @# @4 c. O
debugfs:mi%26lt;196829%26gt;
: x5 w/ @" ^2 E. n+ a
; _6 w2 C: T" n. I/ E# ~ Mode[0100644]
4 ^0 \2 Z5 n3 G- u* k. r5 o5 d. I ~! T* T8 _9 a9 _3 ]
UserID[0]
; h% a$ R* `! v* b5 }, H/ n9 m
) Y$ W2 E; h8 N5 f* B) M GroupID[0]
7 w6 W4 P0 R7 k" r( N8 r* L2 \" W
Size[149500]
) X/ i' F1 u# J+ f2 M" ?" S+ ]
5 C$ G* s0 f" n. K, _ Creationtime[0x31a9a574]
5 {1 t, z4 s/ e, v1 j3 m9 Y( J) q6 Y) M# J# Y% m
Modificationtime[0x31a9a574]
* f$ o7 y% s5 @9 b5 T2 R/ q% E& S) P5 [6 }1 X
Accesstime[0x31a21dd1]
- v8 @7 F3 R9 R3 Z3 g- r3 H4 S. _* x% R T* y6 c
Deletiontime[0x31a9a574]0
% R Q! a1 Y& j+ l" Z5 {3 `9 N: u9 B4 q8 r
Linkcount[0]1
1 u: L q7 F2 }6 H* d8 d. v' j% T% a8 U& a0 V- B' U
Blockcount[38]
/ t; F7 j7 i$ B( p
2 D3 y' S. q* g6 |' C( H3 p K
Fileflags[0x0]
2 g- r0 A1 o% [2 L$ v/ m; L: z
) o" u0 a! n! |3 D% |/ Y2 ]3 m& ^* {
Reserved1[0]
9 _, h- O% z x2 t
( ~! V5 O2 Q8 r7 ^$ i5 u" _, v( q Fileacl[0]
7 y: |9 v1 K$ T4 K% C g
* x. N7 n9 y: J3 g( Z- T3 i
Directoryacl[0]
/ e0 Y4 }* v: l$ C0 v
! k3 T) T! t' b# g3 ]
Fragmentaddress[0]
* n+ {: B. ?- Q5 T7 Q$ i4 b
$ F$ O; W" G: m+ L
Fragmentnumber[0]
. S2 `/ B: _- ~9 ]: d2 P k+ i$ s. w4 ~/ f
( r* v% t3 c9 V) y
Fragmentsize[0]
. ^: F* p$ p, b9 K; `
# W5 b* w* C8 I/ y2 P2 y/ y
DirectBlock#0[594810]
+ |, Z# K- V0 r3 F$ C( i
/ v: x) `6 A# r. c …………………………….
, V5 ?! G' T0 _! M
! s' v4 z) Z+ l+ r& V( O6 m# f' }; m TripleIndirectBlock[0]
4 L# h* R/ V2 U9 b* L
/ f7 |6 Y& X- j8 ^$ J: | 使用mi指令后每次显示一行信息以供编辑,其它行可以直接按回车表示确认,把deletiontime改成0(未删除),Linkcount改成1。改好后退出debugfs:
: ~1 Y; J' q6 O
3 w3 b# f& q0 s% v1 c2 ~& u, v& c debugfs:quit
9 D" I) Z' f( d5 C3 U3 T
6 ^" n8 B* {! C N# F; | 然后用fsck检查/dev/hda5
+ A/ f6 j4 h" ?+ j% h
% q7 B5 P% d0 G( [ fsck/dev/hda5
/ o) F ^* b& ?: f! B6 a1 V
8 v- c& a- n' l: B: A8 f 程序会说找到丢失的数据块,放在lost+found里面。这个目录里的文件就是我们要的。