########  출처 : http://kldp.org/node/103288  ########

Fedora 10 패키지 목록을 살펴보던 중 호기심을 자극하는 패키지가 하나 있었다. 뭔가하고 살펴보니 ext3 파일 시스템에서 지워진 파일의 복구를 해주는 놈이다.


ext2와 다른 특성으로 인해 ext3에서 지워진 파일의 복구는 꽤 어려운 명령어들을 알아야했고 복구율도 좋지 않았었다. 하지만 ext3grep은 이러한 생각을 바꾸게 만들기에 충분했다.


소스 다운로드는 http://code.google.com/p/ext3grep/ 에서 할 수 있고 Fedora나 Debian의 최신 버전에는 포함되어 있으니 해당 배포판의 패키지 관리자로 설치하면 된다.


설치를 하고 간단한 테스트를 해보았다. 시간상 1GB정도의 파티션을 만들고 테스트를 진행했다.


 # mkfs.ext3 /dev/sdb1 # mount /dev/sdb1 /mnt/test/ # df -h /dev/sdb1 966M 18M 899M 2% /mnt/test 

몇개의 디렉토리와 파일을 만들었다.

 # ls * test1.txt test2.txt 테스트.txt 테스트2.txt dir1: dir1.txt dir2: dir2.txt dir3: dir3.txt lost+found: 디렉토리1: 디렉토리1.txt 디렉토리2: 디렉토리2.txt 디렉토리3: 디렉토리3.txt 

그 중에 몇개를 삭제했다.

# rm -rf dir2 dir3 test2.txt 디렉토리1 디렉토리3 테스트.txt 

이제 unmount 하고 실제 ext3grep 을 사용할 차례다.

 # umount /mnt/test 

 –dump-names 로 경로를 포함한 파일들의 경로를 알 수 있다.

 # ext3grep ––dump-names /dev/sdb1 Running ext3grep version 0.10.1 Number of groups: 8 Minimum / maximum journal block: 562 / 4664 Loading journal descriptors… sorting… done The oldest inode block that is still in the journal, appears to be from 1235694214 = Fri Feb 27 09:23:34 2009 Number of descriptors in journal: 269; min / max sequence numbers: 2 / 40 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: DDD+DD+++++++++++++++++D+DD+++++++++ Searching group 1: + Searching group 2: + Searching group 3: + Searching group 4: + Searching group 5: + Searching group 6: + Searching group 7: Writing analysis so far to ’sdb1.ext3grep.stage1′. Delete that file if you want to do this stage again. Result of stage one: 8 inodes are referenced by one or more directory blocks, 4 of those inodes are still allocated. 7 inodes are referenced by more than one directory block, 3 of those inodes are still allocated. 0 blocks contain an extended directory. Result of stage two: 4 of those inodes could be resolved because they are still allocated. 4 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. dir1 dir1/.dir1.txt.swp dir1/dir1.txt dir2 dir2/.dir2.txt.swp dir2/dir2.txt dir3 dir3/.dir3.txt.swp dir3/dir3.txt lost+found test1.txt test2.txt 디렉토리1 디렉토리1/.디렉토리1.txt.swp 디렉토리1/디렉토리1.txt 디렉토리2 디렉토리2/.디렉토리2.txt.swp 디렉토리2/디렉토리2.txt 디렉토리3 디렉토리3/.디렉토리3.txt.swp 디렉토리3/디렉토리3.txt 테스트.txt 테스트2.txt 

위 명령어를 실행한 후 ext3grep.stage1, ext3grep.stage2 파일이 생성되는데 inode와 block의 정보를 담고 있다. 한번 생성되면 다른 명령어를 실행할때 재사용되기 때문에 검색에 소요되는 시간이 줄어든다.

 # cat sdb1.ext3grep.stage1 # Stage 1 data for /dev/sdb1. # Inodes and directory start blocks that use it for dir entry ‘.’. # INODE : BLOCK [BLOCK …] 2 : 556 573 597 605 610 682 688 698 703 713 719 732 859 11 : 557 15713 : 740 792 800 805 40960 31425 : 582 659 666 671 79872 47137 : 571 620 628 633 112640 62849 : 578 645 651 145408 78561 : 736 774 780 172032 94273 : 730 749 757 762 204800 # Extended directory blocks. # END # cat sdb1.ext3grep.stage2 # Stage 2 data for /dev/sdb1. # Inodes path and directory blocks. # INODE PATH BLOCK [BLOCK …] 2 ” 556 11 ‘lost+found’ 557 15713 ‘디렉토리3′ 40960 31425 ‘dir3′ 79872 47137 ‘dir1′ 112640 62849 ‘dir2′ 145408 78561 ‘디렉토리2′ 172032 94273 ‘디렉토리1′ 204800 # END 

–restore-all 은 해당 장치의 모든 파일을 명령어가 실행된 위치에 RESTORED_FILES라는 디렉토리를 생성하고 그 안에 복구해준다. 명령어를 실행하기 전에 충분한 공간이 있는지 확인하자.


** 명령어를 실행시키는 현재 디렉토리에 복구파일을 저장시킨다. **

 # ext3grep ––restore-all /dev/sdb1 Running ext3grep version 0.10.1 Number of groups: 8 Minimum / maximum journal block: 562 / 4664 Loading journal descriptors… sorting… done The oldest inode block that is still in the journal, appears to be from 1235694214 = Fri Feb 27 09:23:34 2009 Number of descriptors in journal: 269; min / max sequence numbers: 2 / 40 Writing output to directory RESTORED_FILES/ 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: DDD+DD+++++++++++++++++D+DD+++++++++ Searching group 1: + Searching group 2: + Searching group 3: + Searching group 4: + Searching group 5: + Searching group 6: + Searching group 7: Writing analysis so far to ’sdb1.ext3grep.stage1′. Delete that file if you want to do this stage again. Result of stage one: 8 inodes are referenced by one or more directory blocks, 4 of those inodes are still allocated. 7 inodes are referenced by more than one directory block, 3 of those inodes are still allocated. 0 blocks contain an extended directory. Result of stage two: 4 of those inodes could be resolved because they are still allocated. 4 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. Restoring dir1/.dir1.txt.swp Restoring dir1/dir1.txt Restoring dir2/.dir2.txt.swp Restoring dir2/dir2.txt Restoring dir3/.dir3.txt.swp Restoring dir3/dir3.txt Restoring test1.txt Restoring test2.txt Restoring 디렉토리1/.디렉토리1.txt.swp Restoring 디렉토리1/디렉토리1.txt Restoring 디렉토리2/.디렉토리2.txt.swp Restoring 디렉토리2/디렉토리2.txt Restoring 디렉토리3/.디렉토리3.txt.swp Restoring 디렉토리3/디렉토리3.txt Restoring 테스트.txt Restoring 테스트2.txt # cd RESTORED_FILES/ # ls * test1.txt test2.txt 테스트.txt 테스트2.txt dir1: dir1.txt dir2: dir2.txt dir3: dir3.txt lost+found: 디렉토리1: 디렉토리1.txt 디렉토리2: 디렉토리2.txt 디렉토리3: 디렉토리3.txt 

–restore-all 명령어와 함께 사용할 수 있는 필터가 여러개 있는데 –after 옵션을 주면 그 시간 이후의 파일들만 복구해준다. unix time을 적어주면 된다.

 # ext3grep ––restore-all –after=1235694514 /dev/sdb1 Running ext3grep version 0.10.1 Only show/process deleted entries if they are deleted on or after Fri Feb 27 09:28:34 2009. Number of groups: 8 Minimum / maximum journal block: 562 / 4664 Loading journal descriptors… sorting… done The oldest inode block that is still in the journal, appears to be from 1235694214 = Fri Feb 27 09:23:34 2009 Number of descriptors in journal: 269; min / max sequence numbers: 2 / 40 Loading sdb1.ext3grep.stage2… done Not undeleting “dir1/.dir1.txt.swp” because it was deleted before 1235694514 (32767) Restoring dir1/dir1.txt Not undeleting “dir2/.dir2.txt.swp” because it was deleted before 1235694514 (1235694303) Not undeleting “dir2/dir2.txt” because it was deleted before 1235694514 (1235694303) Not undeleting “dir3/.dir3.txt.swp” because it was deleted before 1235694514 (1235694303) Not undeleting “dir3/dir3.txt” because it was deleted before 1235694514 (1235694303) Restoring test1.txt Not undeleting “test2.txt” because it was deleted before 1235694514 (1235694287) Not undeleting “디렉토리1/.디렉토리1.txt.swp” because it was deleted before 1235694514 (1235694287) Not undeleting “디렉토리1/디렉토리1.txt” because it was deleted before 1235694514 (1235694287) Not undeleting “디렉토리2/.디렉토리2.txt.swp” because it was deleted before 1235694514 (1235694287) Restoring 디렉토리2/디렉토리2.txt Not undeleting “디렉토리3/.디렉토리3.txt.swp” because it was deleted before 1235694514 (1235694404) Not undeleting “디렉토리3/디렉토리3.txt” because it was deleted before 1235694514 (1235694404) Not undeleting “테스트.txt” because it was deleted before 1235694514 (1235694404) Restoring 테스트2.txt 

특정 이름의 파일만 복구 하려면 –restore-file 다음에 파일명을 써주면 된다.

 # ext3grep ––restore-file 테스트.txt /dev/sdb1 Running ext3grep version 0.10.1 Number of groups: 8 Minimum / maximum journal block: 562 / 4664 Loading journal descriptors… sorting… done The oldest inode block that is still in the journal, appears to be from 1235694214 = Fri Feb 27 09:23:34 2009 Number of descriptors in journal: 269; min / max sequence numbers: 2 / 40 Writing output to directory RESTORED_FILES/ Loading sdb1.ext3grep.stage2… done Restoring 테스트.txt # cd RESTORED_FILES/ # ls 테스트.txt 

디렉토리 밑에 있는 파일이라면 경로까지 정확하게 써주면 된다. 경로를 포함한 파일명은 위에서 한번 실행했던 –dump-names로 알 수 있다.

 # ext3grep ––restore-file dir2/dir2.txt /dev/sdb1 Running ext3grep version 0.10.1 Number of groups: 8 Minimum / maximum journal block: 562 / 4664 Loading journal descriptors… sorting… done The oldest inode block that is still in the journal, appears to be from 1235694214 = Fri Feb 27 09:23:34 2009 Number of descriptors in journal: 269; min / max sequence numbers: 2 / 40 Loading sdb1.ext3grep.stage2… done Restoring dir2/dir2.txt 

더 많은 옵션이 있지만 일반적인 사용자라면 이정도만 알아도 충분히 복구할 수 있을 것이다. 이름처럼 ext3에 대해서 복구를 해주기 때문에 포맷이 되었거나 다른 파일시스템에서는 복구가 안된다.


마지막으로 노파심에서 한마디 하자면 실수로 파일을 삭제했을때에는 최대한 빨리 해당 장치를 unmount 해서 덮어써지지 않게 해야한다.


자세한 정보는 저자의 홈페이지에서 확인하자.

########  아래는 http://blog.naver.com/nothingknow/120057940500 참고 내용 ########


ext3 파일시스템에서 실수로 지운 파일을 undelte하는 법이 있다. 바로 ext3grep 이라는 프로그램을 사용하는 것이다.


ext3에서 undelete를 할 수 있는 프로그램과 하우투 문서는 올해 3월에 세상에 알려지게 되었고 본인은 그사실을 당시에 접했었다. 아마, 현재까지도 한국 유저들에게 널리 알려지지는 않았을 것이다. 하지만 딱히 undelete 를 해야하는 상황에 처해있지 않았기 때문에 잊고 지냈었다. 그런데 얼마전에 실수로


# rm -rf music


를 해버렸다. 그래서 내가 모아둔 mp3 수십곡을 날리게 되었다. 뭐.. bittorrent 를 사용해서 받으면 그만이지만 한 번 undelete 를 해보고 싶다는 생각에 사로잡히게 되었다.



결론부터 말하자면, 내 시스템에서 ext3grep이 완전히 정상 작동을 하지는 않는다. 문제점을 해결하는 방법은 더 모색해봐야한다. 하지만 부분적인 기능은 제대로 작동하기 때문에 시범적으로 몇개의 mp3를 복구할 수 있었다.



사용기는 다음과 같다.


======================


ext3grep 을 받을 수 있는 곳은 여기다. http://groups.google.com/group/ext3grep

처음 ext3grep을 적용하는 디바이스 이미지에 대해서는


# ext3grep /dev/sda2 –superblock


을 해주면된다. 그러면 stage1 과 stage2 파일이 생성되는데 이것은 다음 적용 때 캐시 역할을 하여 동작 효율을 향상시킨다.


여기서 알아둘 것은 /dev/sda2 는 read-only 이거나 unmount 상태이어야 한다는 것이다. write 가 되어도 ext3grep 이 작동은 하지만 지워진 파일의 데이터위에 혹시 다른 데이터가 덮어씌어질 수 있기 때문에 복구하기 전까진 write를 해선 안된다. 그러므로 자신이 실수로 무언가를 지웠다는 생각이 들면 곧장


#mount -o remount,ro /dev/sda2


를 해줘야한다. 그래야 데이터를 손상 입지 않고 온전히 복구할 가능성이 높아진다. 본인은 /dev/sda2 가 / 파티션이기 때문에 몇 주째 /dev/sda2 를 루트디렉토리라 삼은 시스템을 부팅하지 않고 있다. 대신 Live CD 를 이용하여 부팅한 뒤 /dev/sda2 에 접근한다. (슬랙웨어 기반의 SLAX 라는 라이브 시디를 사용하고 있다. 슬랙웨어여 영원하길 ~~)


그다음으로 해볼 것은


#ext3grep /dev/sda2 –ls –inode 2


이다. 이명령은 2번 아이노드에 대한 정보를 보여준다. 2번아이노드는 디렉토리를 가리키며 / 이다. 출력 결과는 / 디렉토리의 내용을 보여준다. 즉 최상위 디렉토리의 하위디렉토리 목록이 나열된다. 그중 관심있는 디렉토리의 inode 를 골라서 다음 명령을 내린다.


# ext3grep /dev/sda2 –print –inode 753665


Running ext3grep version 0.9.0
Number of groups: 68
Minimum / maximum journal block: 1065 / 34926
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1218170978 = Fri Aug  8 04:49:38 2008
Journal transaction 45442 wraps around, some data blocks might have been lost of this transaction.
Number of descriptors in journal: 29820; min / max sequence numbers: 43947 / 51670


Hex dump of inode 753665:
0000 | 00 00 6a b7 2e 00 00 00 80 08 00 00 00 10 00 00 | ..j………….
0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 | …………….
0020 | cc ed af bf a4 ed af bf d8 ed af 01 00 00 00 00 | …………….
0030 | cc ed af bf a4 ed af bf d8 ed af bf 0b 9c 05 08 | …………….
0040 | a0 f0 0d 08 f8 ec 16 08 80 08 00 00 00 00 00 00 | …………….
0050 | 09 00 00 00 a0 c7 f2 0a 63 60 31 ff 00 10 00 00 | ……..c`1…..
0060 | 00 00 00 00 00 00 00 00 00 00 00 00 aa f5 af bf | …………….
0070 | 64 ee af bf d4 ed af bf 78 ee af bf f5 58 07 08 | d…….x….X..


Inode is Allocated
Group: 46
Generation Id: 3337215777
uid / gid: 0 / 0
mode: drwxr-xr-x
size: 4096
num of links: 40
sectors: 8 (–> 0 indirect blocks).


Inode Times:
Accessed:       1223716241 = Sat Oct 11 09:10:41 2008
File Modified:  1223716243 = Sat Oct 11 09:10:43 2008
Inode Modified: 1223716243 = Sat Oct 11 09:10:43 2008
Deletion time:  0


Direct Blocks: 1515520
Loading sda2.ext3grep.stage2……………………………………………………………………………………………………………………………………………………………………………….. done
The first block of the directory is 1515520.
Inode 753665 is directory "root".
Directory block 1515520:
          .– 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  753665                                         drwxr-xr-x  .
   1    2 d       2                                         drwxr-xr-x  ..
   2    3 r  753666                                         rrw-r–r–  loadlin16c.txt
   3    4 r  753667                                         rrw-r–r–  loadlin16c.zip
   4    5 r  759497                                         rrw-r–r–  .xinitrc
   5    6 d  827703                                         drwxr-xr-x  .emacs.d
   6    7 d  827705                                         drwx——  .kde
   7    8 d  827714                                         drwxr-xr-x  .qt
   8    9 d   88463                                         drwxr-xr-x  .mc
   9   10 r  491877                                         rrw——-  .Xauthority
  10   11 d  115601                                         drwx——  Desktop
  11   12 d  115855                                         drwx——  .gxine
  12   13 d  115963                                         drwx——  .dbus
  13   14 d  115866                                         drwx——  .mozilla
  14   16 r  761619                                         rrw-r–r–  ee
  15   16 d  778695  D 1223716314 Sat Oct 11 09:11:54 2008  drwxr-xr-x  music
  16   17 r  761598                                         rrw——-  .kderc


    (…………….중략……………….)



  82   83 r  491883                                         rrw——-  .serverauth.3130
  83   90 r  491884                                         rrw——-  .serverauth.3216
  85   90 r  491887  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Mozart]Piano_Concerto_No21_K464.mp3
  86   90 r  491888  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Haydn]String_Quarter_Op64_No4_LARK.mp3
  87   88 r  491885  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Bach]Brandenburg_Concerto_No4_BWV1049.mp3
  88   90 r  491889  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Beethoven]Violin_Sonata_No5_Spring.mp3
  90   91 r  491893                                         rrwxr-xr-x  ripping_each.sh
  91  end r  491892                                         rrwxr-xr-x  ripping_each.sh~
  92   93 r  491880  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Bizet]L_Arlesienne_Suite_No2.mp3
  93   94 r  491894  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Chopin]Etude_Op10_No12.mp3
  94   96 r  491895  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Greig]Piano_Concerto_A_minor_Op16.mp3
  95   96 r  491896  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Debussy]Arabesque_No1.mp3
  96  100 r  491897  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Vivaldi]Four_Seasons_Spring.mp3
  97   98 r  491898  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Beethoven]Piano_Sonata_No14_1st_mov..mp3
  98   99 r  491899  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Beethoven]Piano_Sonata_No8_2nd_mov..mp3
  99  100 r  491900  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Dvorak]Slavonic_Dance_Op46_No2.mp3
 100  end r  491901  D 1223716242 Sat Oct 11 09:10:42 2008  rrw-r–r–  [Vivaldi]Mandolin_Concerto_RV125.mp3



그랬다. 실수로 music 디렉토리를 통째로 날렸다. music 디렉토리에 대해 탐구해보자


삭제시각은 1223716314 유닉스 시간이다. (유닉스 시간은 1970년 1월 1일 자정을 시작시기로 하여 초단위로 표시한다.)


또 그 하위에 뭐가 있었나 들여다보자
# ext3grep /dev/sda2 –print –inode 778695
Running ext3grep version 0.9.0
Number of groups: 68
Minimum / maximum journal block: 1065 / 34926
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1218170978 = Fri Aug  8 04:49:38 2008
Journal transaction 45442 wraps around, some data blocks might have been lost of this transaction.
Number of descriptors in journal: 29820; min / max sequence numbers: 43947 / 51670


Hex dump of inode 778695:
0000 | 00 a3 82 b7 2f 00 00 00 80 08 00 00 00 10 00 00 | …./………..
0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 | …………….
0020 | 2c 92 f5 bf 04 92 f5 bf 38 92 f5 01 00 00 00 00 | ,…….8…….
0030 | 2c 92 f5 bf 04 92 f5 bf 38 92 f5 bf 0b 9c 05 08 | ,…….8…….
0040 | a0 f0 0d 08 f8 ec 16 08 80 08 00 00 00 00 00 00 | …………….
0050 | 09 00 00 00 a0 87 fa 0a 63 60 31 ff 00 10 00 00 | ……..c`1…..
0060 | 00 00 00 00 00 00 00 00 00 00 00 00 aa 95 f5 bf | …………….
0070 | c4 92 f5 bf 34 92 f5 bf d8 92 f5 bf f5 58 07 08 | ….4……..X..


Inode is Unallocated
Group: 47
Generation Id: 3432577881
uid / gid: 0 / 0
mode: drwxr-xr-x
size: 0
num of links: 0
sectors: 0 (–> 0 indirect blocks).


Inode Times:
Accessed:       1223716243 = Sat Oct 11 09:10:43 2008
File Modified:  1223716314 = Sat Oct 11 09:11:54 2008
Inode Modified: 1223716314 = Sat Oct 11 09:11:54 2008
Deletion time:  1223716314 = Sat Oct 11 09:11:54 2008


Direct Blocks:
Loading sda2.ext3grep.stage2……………………………………………………………………………………………………………………………………………………………………………….. done
The first block of the directory is 1560942.
Inode 778695 is directory "root/music".
Directory block 1560942:
          .– 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  778695  D 1223716314 Sat Oct 11 09:11:54 2008  drwxr-xr-x  .
   1  end d  753665                                         drwxr-xr-x  ..
   2  end d  778696  D 1223716243 Sat Oct 11 09:10:43 2008  dr-x——  ??4吏?
   3    4 d  793374  D 1223716242 Sat Oct 11 09:10:42 2008  drwxr-xr-x  classic_golden_best
   4    6 r  778710  D 1223716242 Sat Oct 11 09:10:42 2008  rr——–  [The Feeling] Fill My Little World.wma
   6  end d  973927  D 1223716243 Sat Oct 11 09:10:43 2008  dr-x——  James Blunt – All The Lost Souls (256Kbps) + covers
   7  end d  906617  D 1223716243 Sat Oct 11 09:10:43 2008  dr-x——  James Blunt – back to bedlam
   8  end l  778712  D 1223716242 Sat Oct 11 09:10:42 2008  lrwxrwxrwx  torrentmusic -> ../foo/bitflu/chroot/workdir/committed/
   9  end d  778713  D 1223716242 Sat Oct 11 09:10:42 2008  dr-x——  05. BoA – [2005.07.27] – Girls on Top



그렇다. 내가 복구해야할 대상이 이것들이다. 쉽게 받을 수 있는 것들이지만, 오기가 생겨서 꼭 복구해내고 말테다.


만약 ext3grep 이 정상 작동한다면 다음 명령어로 복구할 수 있다.



# ext3grep /dev/sda2 –restore-all –after 1223716242   —> 유닉스 타임으로 1223716242 시각 이후 삭제된 파일들만 복구하라는 얘기



하지만 프로그램에 문제가 있어서 이 명령이 제대로 작동하지 않고 내 /dev/sda2 에 있는 모든 파일을 전부 복사하려든다.


원래대로라면


# ext3grep /dev/sda2 –dump-names


를 하면 지워진 파일 목록만 보여야한다. 하지만 현재로썬 이 명령을 내리면 /dev/sda2 에 지워지지 않은 모든 파일과 지워진 파일 목록이 모두 나와서 무려 243199개의 리스트가 나온다 ㅡㅡ; 즉, 현재상태에서는 오작동하여 restore-all –after 1223716242 를 하면 243199개의 파일을 모두 복사할 것이다…이것을 고치기 위해서는 내가 직접 프로그램 소스를 손보는 수밖에 없을 듯하다. ( 공식 사이트에서나 하우투문서에서나 모두 강조하길, "이 프로그램이 자동으로 당신이 원하는대로 동작하길 기대하지 말아라. 당신은 당신이 무엇을 하는지 알아야 이 프로그램을 제대로 사용할 수 있다"라고 말한다…. )



–restore-all –after 콤비네이션을 이용하여 많은 개수의 파일을 복구해내려는 시도는 일단 실패로 돌아갔고 시험삼아 하나의 파일을 복구해봤다.


# ext3grep /dev/sda2 –restore-file root/[Vivaldi]Mandolin_Concerto_RV125.mp3
Running ext3grep version 0.9.0
Number of groups: 68
Minimum / maximum journal block: 1065 / 34926
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1218170978 = Fri Aug  8 04:49:38 2008
Journal transaction 45442 wraps around, some data blocks might have been lost of this transaction.
Number of descriptors in journal: 29820; min / max sequence numbers: 43947 / 51670
Loading sda2.ext3grep.stage2……………………………………………………………………………………………………………………………………………………………………………… done
Restoring root/[Vivaldi]Mandolin_Concerto_RV125.mp3


이 명령을 내리면 현재 디렉토리에 RESTORE_FILE 디렉토리가 생성되고 그 하위에 파일이 복구된다. 즉, /dev/sda2 에 있는 데이터가 되살아나는 게 아니라 삭제된 데이터를 현재 디렉토리로 복사해오는 것이다.



같은 역할을 하지만 이렇게 해도 된다.



# ext3grep /dev/sda2 –restore-inode 491901
Running ext3grep version 0.9.0
Number of groups: 68
Minimum / maximum journal block: 1065 / 34926
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1218170978 = Fri Aug  8 04:49:38 2008
Journal transaction 45442 wraps around, some data blocks might have been lost of this transaction.
Number of descriptors in journal: 29820; min / max sequence numbers: 43947 / 51670
Restoring inode.491901



이 글을 읽는 분은 '그렇다면 스크립트를 써서 for 문과 –restore-file 조합을 적용하면 되지 않는가'라고 생각할 수 있다. 맞다. 하지만 그렇게 하면 시간이 너무 오래걸린다.


Loading sda2.ext3grep.stage2……………………………………………………………………………………………………………………………………………………………………………… done


특히 stage2 캐시를 읽어들이는 부분이 만만치 않은 시간이 소요되기 때문에 수많은 파일을 복구하는데 시간 손해를 많이 보게된다. 반면에 –retore-all 을 쓰면 불과 3~4초만에 수백메가에 달하는 파일이 복구된다.

########  아래는 http://www.lug.or.kr/home/bbs/board.php?bo_table=centos_book&wr_id=498 참고 내용 ########



본 문서에서는 ext3 파일시스템으로 만들어진 파티션에서
삭제한 파일을 쉽게 복구할 수 있는 ext3grep에 대하여 공부하도록 하자.

명심/주의) 단, 복구 대상 파티션을 이미 재포맷(fdisk or mkfs.ext3 등)하였다면 복구하지 못한다.

CentOS를 비롯한 최근 대부분의 리눅스 배포판들은 기본 파일시스템으로 ext3를 사용하고 있다.

누구나 리눅스 시스템에서 한순간의 실수로(rm -f) 파일을 잘못 삭제할 수있다.
이런 상황에서 "리눅스에서 삭제한 파일을 쉽게 복구할 수 있는 방법은 없을까?" 라고 고민해본 경험이 있을것이다.

이런 경우 아주 유용하게 사용할 수 있는 유틸리티가 있어서 소개하고자 한다.

ext3grep 유틸리티를 사용하기 위해서는 먼저 특정 하드디스크 파티션의 파일시스템을 ext3로 사용하고 있어야 한다.

테스트를 위하여 파티션을 하나 생성하고 생성한 파티션에서 파일을 생성한 다음 삭제하고

삭제한 파일을 복구하는 예제를 통하여 공부해 보도록 하겠다.

단, 본 문서는 필자가 현재 사용중인 CentOS 5.3을 기준으로 작성하였으며
추가적으로 장착한 /dev/hdb 디스크는 128M 용량이다. ^^;;

만약 여분의 하드디스크 파티션이 없다면 dd 명령으로 이미지를 만들어서 테스트해보기 바란다.
[마지막 부분 참조]

1. 먼저 ext3grep 유틸리티를 설치하기에 앞서 rpmforge.net 저장소를 사용할 수 있도록 한다.

ext3grep 유틸리티는 기본 패키지에서 제공하지 않고 있지만,
rpmforge.net에서 제공하고 있으므로, 아래와 같이 rpmforge.net을 이용할 수 있도록
아래의 패키지를 다운로드 받고 설치한다.

RHEL5 / CentOS-5
i386: http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
x86_64: http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm


[root@localhost src]# pwd
/usr/local/src
[root@localhost src]# lftpget http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
[root@localhost src]# ls
rpmforge-release-0.3.6-1.el5.rf.i386.rpm
[root@localhost src]# rpm -ivh rpmforge-release-0.3.6-1.el5.rf.i386.rpm
준비 중…               ########################################### [100%]
   1:rpmforge-release       ########################################### [100%]
[root@localhost src]# rpm -qa|grep rpmforge
rpmforge-release-0.3.6-1.el5.rf
[root@localhost src]#

2. yum을 사용하여 ext3grep 패키지를 검색하고 검색이 되면 설치한다.

[root@localhost src]# yum search ext3grep
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * rpmforge: apt.sw.be
 * base: centos.mirror.cdnetworks.com
 * updates: centos.mirror.cdnetworks.com
 * addons: centos.mirror.cdnetworks.com
 * extras: centos.mirror.cdnetworks.com
===================================== Matched: ext3grep ======================================
ext3grep.i386 : Tool to investigate deleted content on ext3 filesystem for recovery
[root@localhost src]#

위에서 보는 것과 같이 ext3grep 패키지를 검색하였다.
검색이 되었다면 설치하도록 한다.

[root@localhost src]# yum install ext3grep -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * rpmforge: apt.sw.be
 * base: centos.mirror.cdnetworks.com
 * updates: centos.mirror.cdnetworks.com
 * addons: centos.mirror.cdnetworks.com
 * extras: centos.mirror.cdnetworks.com
Setting up Install Process
Parsing package install arguments
Resolving Dependencies
–> Running transaction check
—> Package ext3grep.i386 0:0.10.0-1.el5.rf set to be updated
–> Finished Dependency Resolution


Dependencies Resolved


==============================================================================================
 Package              Arch             Version                     Repository            Size
==============================================================================================
Installing:
 ext3grep             i386             0.10.0-1.el5.rf             rpmforge             140 k


Transaction Summary
==============================================================================================
Install      1 Package(s)
Update       0 Package(s)
Remove       0 Package(s)


Total download size: 140 k
Downloading Packages:
ext3grep-0.10.0-1.el5.rf.i386.rpm                                      | 140 kB     00:02
Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing     : ext3grep                                          [1/1]


Installed: ext3grep.i386 0:0.10.0-1.el5.rf
Complete!
[root@localhost src]#

이번에는 설치한 ext3grep 패키지의 정보와 이 패키지에 포함되어 있는 파일들의 리스트를 보도록 하자.

[root@localhost src]# rpm -qi ext3grep
Name        : ext3grep                     Relocations: (not relocatable)
Version     : 0.10.0                            Vendor: Dag Apt Repository, http://dag.wieers.com/apt/
Release     : 1.el5.rf                      Build Date:
Install Date:                                  Build Host: lisse.hasselt.wieers.com
Group       : Applications/File             Source RPM: ext3grep-0.10.0-1.el5.rf.src.rpm
Size        : 342187                           License: GPL
Signature   : DSA/SHA1, 2008년 11월 05일 (수) 오전 02시 32분 36초, Key ID a20e52146b8d79e6
Packager    : Dag Wieers <dag@wieers.com>
URL         : http://code.google.com/p/ext3grep/
Summary     : Tool to investigate deleted content on ext3 filesystem for recovery
Description :
ext3grep is a tool to investigate an ext3 filesystem for deleted content and
possibly recover it.

[root@localhost src]# rpm -ql ext3grep
/usr/bin/ext3grep
/usr/share/doc/ext3grep-0.10.0
/usr/share/doc/ext3grep-0.10.0/INSTALL
/usr/share/doc/ext3grep-0.10.0/LICENSE.GPL2
/usr/share/doc/ext3grep-0.10.0/NEWS
/usr/share/doc/ext3grep-0.10.0/README
[root@localhost src]#

패키지의 구성이 매우 심플하다. 다큐먼트와 ext3grep 실행파일만으로 구성되어 있다.

2. 이제 본격적으로 ext3grep 유틸리티를 사용하기 위해 필자는 /dev/hdb 하드디스크(1G)를 장착하고
이 하드디스크에 파티션(hdb1)을 생성하고 ext3 파일시스템으로 포맷하도록 하겠다.

[root@localhost src]# fdisk -l


Disk /dev/hda: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes


   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1         913     7333641   83  Linux
/dev/hda2             914        1044     1052257+  82  Linux swap / Solaris


Disk /dev/hdb: 1073 MB, 1073741824 bytes
16 heads, 63 sectors/track, 2080 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes


Disk /dev/hdb doesn't contain a valid partition table
[root@localhost src]#

위와 같이 fdisk -l 명령을 사용하여 파티션 리스트를 보면 첫번째 하드디스크에 2개의 파티션이 있으며, 마지막 라인을 보면 hdb 디스크가 장착되어 있지만 파티션 테이블이 없다는 메시지를 볼 수 있다.

이제 파티션을 만들고 ext3 파일시스템으로 포맷하도록 한다.

[root@localhost src]# fdisk /dev/hdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that, of course, the previous
content won't be recoverable.


The number of cylinders for this disk is set to 2080.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)


Command (m for help): p


Disk /dev/hdb: 1073 MB, 1073741824 bytes
16 heads, 63 sectors/track, 2080 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes


   Device Boot      Start         End      Blocks   Id  System


Command (m for help): m
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
   x   extra functionality (experts only)


Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-2080, default 1): 1
Last cylinder or +size or +sizeM or +sizeK (1-2080, default 2080): 2080


Command (m for help): p


Disk /dev/hdb: 1073 MB, 1073741824 bytes
16 heads, 63 sectors/track, 2080 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes


   Device Boot      Start         End      Blocks   Id  System
/dev/hdb1               1        2080     1048288+  83  Linux


Command (m for help): w
The partition table has been altered!


Calling ioctl() to re-read partition table.
Syncing disks.
[root@localhost src]#

이와 같이 파티션을 생성하면 기본적으로 Linux 파티션타입으로 자동 지정되기 때문에 t 명령을 사용하여 파일시스템타입을 변경하지 않았다.


[root@localhost src]# fdisk -l


Disk /dev/hda: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes


   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1         913     7333641   83  Linux
/dev/hda2             914        1044     1052257+  82  Linux swap / Solaris


Disk /dev/hdb: 1073 MB, 1073741824 bytes
16 heads, 63 sectors/track, 2080 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes


   Device Boot      Start         End      Blocks   Id  System
/dev/hdb1               1        2080     1048288+  83  Linux
[root@localhost src]#

fdisk로 하드디스크의 파티션 정보를 보면 위와 같이 /dev/hdb1 정보를 볼 수 있다.

이제 파티션 포맷을 하도록 한다.

[root@localhost src]# mkfs.ext3 /dev/hdb1
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
131072 inodes, 262072 blocks
13103 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=268435456
8 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376


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


This filesystem will be automatically checked every 21 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@localhost src]#

파일시스템 포맷이 정상적으로 수행되었다.
이제 마운트 하도록 한다.
마운트 포인터는 /test 로 할것이다.

[root@localhost src]# mkdir /test
[root@localhost src]# mount -t ext3 /dev/hdb1 /test

마운트가 되었는지 확인해본다.

[root@localhost src]# mount
/dev/hda1 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)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
/dev/hdb1 on /test type ext3 (rw)
[root@localhost src]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda1             6.8G  3.3G  3.2G  51% /
tmpfs                 125M     0  125M   0% /dev/shm
/dev/hdb1            1008M   18M  940M   2% /test
[root@localhost src]#

3. 이제 /hdb1 파티션이 마운트 되었으므로 ext3grep를 사용해보도록 하자.

2개의 파일과 2개의 디렉토리를 생성한다.

[root@localhost src]# cd /test
[root@localhost test]# pwd
/test
[root@localhost test]# ls
lost+found
[root@localhost test]# echo "test1" > test1.txt
[root@localhost test]# echo "test2" > test2.txt
[root@localhost test]# mkdir dir1
[root@localhost test]# mkdir dir2
[root@localhost test]# ls -l
합계 32
drwxr-xr-x 2 root root  4096 2009-07-01 18:29 dir1
drwxr-xr-x 2 root root  4096 2009-07-01 18:29 dir2
drwx—— 2 root root 16384 2009-07-01 18:22 lost+found
-rw-r–r– 1 root root     6 2009-07-01 18:28 test1.txt
-rw-r–r– 1 root root     6 2009-07-01 18:29 test2.txt
[root@localhost test]# cp test1.txt dir1/
[root@localhost test]# cp test2.txt dir2/
[root@localhost test]# ls *
test1.txt  test2.txt


dir1:
test1.txt


dir2:
test2.txt


lost+found:
[root@localhost test]#

위에서 2개의 파일과 2개의 디렉토리안에 각각 한개의 파일이 존재하도록 구성하였다.
이제 파일을 모두 삭제하도록 하겠다.

[root@localhost test]# rm -rf *
[root@localhost test]# ls -l
합계 0
[root@localhost test]#

4. 앞서 파일과 디렉토리를 모두 삭제하였다.
ext3grep로 파일을 복구할 차례다.

먼저 안전한 복구 작업을 위해 반드시 /dev/hdb1 파티션을 umount 하도록 한다.

[root@localhost test]# cd
[root@localhost ~]# pwd
/root
[root@localhost ~]# umount /test
[root@localhost ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda1             6.8G  3.3G  3.2G  51% /
tmpfs                 125M     0  125M   0% /dev/shm
[root@localhost ~]#

이제 ext3grep 명령의 도움말을 출력해 보도록 하자.

[root@localhost ~]# ext3grep –help
Running ext3grep version 0.10.0
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!
  –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[,ino,…]
                         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).
  –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.
[root@localhost ~]#


/dev/hdb1 파티션에서 삭제된 파일을 모두 검색하기 위해 –dump-names 옵션을 사용해본다.

명령실행후 시간이 조금 소요되므로 기다린다.

[root@localhost ~]# ext3grep –dump-names /dev/hdb1
Running ext3grep version 0.10.0
Number of groups: 8
Minimum / maximum journal block: 585 / 4687
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1246440497 = Wed Jul  1 18:28:17 2009
Number of descriptors in journal: 73; min / max sequence numbers: 2 / 16
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+D+++
Searching group 1: +
Searching group 2:
Searching group 3:
Searching group 4:
Searching group 5: +
Searching group 6:
Searching group 7:
Writing analysis so far to 'hdb1.ext3grep.stage1'. Delete that file if you want to do this stage again.
Result of stage one:
  4 inodes are referenced by one or more directory blocks, 1 of those inodes is still allocated.
  3 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.
  2 inodes could be resolved because all refering blocks but one were journal blocks.
All directory inodes are accounted for!


Writing analysis so far to 'hdb1.ext3grep.stage2'. Delete that file if you want to do this stage again.
dir1
dir1/test1.txt
dir2
dir2/test2.txt
lost+found
test1.txt
test2.txt
[root@localhost ~]#

위의 결과를 보면 hdb1.ext3grep.stage2 파일을 생성하였다고 출력하고 있으며, 이 파일은 재검색시 사용될 것이라고 알려주고 있다.

[root@localhost ~]# ls -l hdb1*
-rw-r–r– 1 root root 238 2009-07-01 18:43 hdb1.ext3grep.stage1
-rw-r–r– 1 root root 171 2009-07-01 18:43 hdb1.ext3grep.stage2
[root@localhost ~]# cat hdb1.ext3grep.stage1
# Stage 1 data for /dev/hdb1.
# Inodes and directory start blocks that use it for dir entry '.'.
# INODE : BLOCK [BLOCK …]
2 : 579 593 601 611 666
11 : 580
16385 : 609 640 61440
81921 : 615 647 194560
# Extended directory blocks.
# END
[root@localhost ~]# cat hdb1.ext3grep.stage2
# Stage 2 data for /dev/hdb1.
# Inodes path and directory blocks.
# INODE PATH BLOCK [BLOCK …]
2 " 579
11 'lost+found' 580
16385 'dir1' 61440
81921 'dir2' 194560
# END
[root@localhost ~]#

물론 –search '파일명' 옵션을 사용하여 특정한 파일을 검색할 수도 있다.

[root@localhost ~]# ext3grep –search test1.txt /dev/hdb1
Running ext3grep version 0.10.0
Number of groups: 8
Minimum / maximum journal block: 585 / 4687
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1246440547 = Wed Jul  1 18:29:07 2009
Number of descriptors in journal: 72; min / max sequence numbers: 3 / 21
Blocks containing "test1.txt": 579 (allocated) 601 (allocated) 611 (allocated) 640 (allocated) 666 (allocated) 61440
[root@localhost ~]#

이제 삭제된 파일중에서 test1.txt, test2.txt 파일만 복구한 다음 /dev/hdb1 파티션을 마운트해 보자.

복구 옵션에서 하나의 파일만 지정하여 복구하기 위해서는 –restore-file 을 사용하고,
모든 파일을 복구하려면 –restore-all 옵션을 사용하면 된다.


아래 예제는 test1.txt 파일만 복구한 것이다.

[root@localhost ~]# ext3grep –restore-file test1.txt /dev/hdb1
Running ext3grep version 0.10.0
Number of groups: 8
Minimum / maximum journal block: 585 / 4687
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1246440547 = Wed Jul  1 18:29:07 2009
Number of descriptors in journal: 72; min / max sequence numbers: 3 / 21
Writing output to directory RESTORED_FILES/
Loading hdb1.ext3grep.stage2… done
Restoring test1.txt
[root@localhost ~]#

위의 결과 메시지에서 보는것과 같이 현재 디렉토리아래에 RESTORED_FILES/ 디렉토리에 복구하였다고 알려주고 있다. 이 디렉토리를 보면 아래와 같이 복구가 정상적으로 완료되었음을 확인할 수 있다.

[root@localhost ~]# ls -l | grep ^d
drwxr-xr-x 2 root root   4096 2009-07-01 19:13 RESTORED_FILES
[root@localhost ~]# ls -l RESTORED_FILES/
합계 4
-rw-r–r– 1 root root 6 2009-07-01 18:28 test1.txt
[root@localhost ~]# cat RESTORED_FILES/test1.txt
test1
[root@localhost ~]#

이번에는 dir2 디렉토리아래의 test2.txt 파일을 복구해보자.

[root@localhost ~]# ext3grep –restore-file dir2/test2.txt /dev/hdb1
Running ext3grep version 0.10.0
Number of groups: 8
Minimum / maximum journal block: 585 / 4687
Loading journal descriptors… sorting… done
The oldest inode block that is still in the journal, appears to be from 1246440547 = Wed Jul  1 18:29:07 2009
Number of descriptors in journal: 72; min / max sequence numbers: 3 / 26
Loading hdb1.ext3grep.stage2… done
Restoring dir2/test2.txt
[root@localhost ~]# ls -l RESTORED_FILES/
합계 8
drwxr-xr-x 2 root root 4096 2009-07-01 19:28 dir2
-rw-r–r– 1 root root    6 2009-07-01 18:28 test1.txt
[root@localhost ~]# ls -l RESTORED_FILES/dir2/
합계 4
-rw-r–r– 1 root root 6 2009-07-01 18:30 test2.txt
[root@localhost ~]# cat RESTORED_FILES/dir2/test2.txt
test2
[root@localhost ~]#

만약 삭제된 모든 파일을 복구하려면 –restore-all 옵션을 사용하면 되지만, 이 경우에는 현재위치의 파티션 용량이 충분한지 확인한 다음 사용하도록 한다.


[참고 : dd 명령으로 이미지를 만들어서 마운트 하기]

[root@localhost ~]# dd if=/dev/zero of=file.img bs=1k count=10000
10000+0 records in
10000+0 records out
10240000 bytes (10 MB) copied, 0.0977925 seconds, 105 MB/s
[root@localhost ~]# losetup /dev/loop0 file.img
[root@localhost ~]# mkfs.ext3 /dev/loop0 10000
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
2512 inodes, 10000 blocks
500 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=10485760
2 block groups
8192 blocks per group, 8192 fragments per group
1256 inodes per group
Superblock backups stored on blocks:
        8193

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

This filesystem will be automatically checked every 32 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@localhost ~]# mkdir /loop0
[root@localhost ~]# mount -t ext3 /dev/loop0 /loop0
[root@localhost ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda1             6.8G  3.3G  3.2G  51% /
tmpfs                 125M     0  125M   0% /dev/shm
/dev/loop0            9.5M  1.1M  7.9M  13% /loop0
[root@localhost ~]# ls /loop0/
lost+found
[root@localhost ~]#


[참고 : 해당 장치명에 존재하는 파일시스템의 수퍼블럭과 블럭 그룹정보를 확인하기 위한 명령 : dumpe2fs]


[root@localhost ~]# dumpe2fs /dev/hdb1
dumpe2fs 1.39 (29-May-2006)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          48501f98-e905-4fec-a98a-e987b4fe38bc
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal resize_inode dir_index filetype sparse_super large_file
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              131072
Block count:              262072
Reserved block count:     13103
Free blocks:              253531
Free inodes:              131062
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      63
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         16384
Inode blocks per group:   512
Filesystem created:       Wed Jul  1 18:22:20 2009
Last mount time:          Wed Jul  1 19:10:44 2009
Last write time:          Wed Jul  1 19:12:56 2009
Mount count:              3
Maximum mount count:      21
Last checked:             Wed Jul  1 18:22:20 2009
Check interval:           15552000 (6 months)
Next check after:         Mon Dec 28 18:22:20 2009
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               128
Journal inode:            8
Default directory hash:   tea
Directory Hash Seed:      9dd1fe3c-ce45-4d9a-83e0-777d03d810d2
Journal backup:           inode blocks
Journal size:             16M


Group 0: (Blocks 0-32767)
  Primary superblock at 0, Group descriptors at 1-1
  Reserved GDT blocks at 2-64
  Block bitmap at 65 (+65), Inode bitmap at 66 (+66)
  Inode table at 67-578 (+67)
  28085 free blocks, 16374 free inodes, 1 directories
  Free blocks: 580-583, 4687-32767
  Free inodes: 11-16384
Group 1: (Blocks 32768-65535)
  Backup superblock at 32768, Group descriptors at 32769-32769
  Reserved GDT blocks at 32770-32832
  Block bitmap at 32833 (+65), Inode bitmap at 32834 (+66)
  Inode table at 32835-33346 (+67)
  32189 free blocks, 16384 free inodes, 0 directories
  Free blocks: 33347-65535
  Free inodes: 16385-32768
Group 2: (Blocks 65536-98303)
  Block bitmap at 65536 (+0), Inode bitmap at 65537 (+1)
  Inode table at 65538-66049 (+2)
  32254 free blocks, 16384 free inodes, 0 directories
  Free blocks: 66050-98303
  Free inodes: 32769-49152
Group 3: (Blocks 98304-131071)
  Backup superblock at 98304, Group descriptors at 98305-98305
  Reserved GDT blocks at 98306-98368
  Block bitmap at 98369 (+65), Inode bitmap at 98370 (+66)
  Inode table at 98371-98882 (+67)
  32189 free blocks, 16384 free inodes, 0 directories
  Free blocks: 98883-131071
  Free inodes: 49153-65536
Group 4: (Blocks 131072-163839)
  Block bitmap at 131072 (+0), Inode bitmap at 131073 (+1)
  Inode table at 131074-131585 (+2)
  32254 free blocks, 16384 free inodes, 0 directories
  Free blocks: 131586-163839
  Free inodes: 65537-81920
Group 5: (Blocks 163840-196607)
  Backup superblock at 163840, Group descriptors at 163841-163841
  Reserved GDT blocks at 163842-163904
  Block bitmap at 163905 (+65), Inode bitmap at 163906 (+66)
  Inode table at 163907-164418 (+67)
  32189 free blocks, 16384 free inodes, 0 directories
  Free blocks: 164419-196607
  Free inodes: 81921-98304
Group 6: (Blocks 196608-229375)
  Block bitmap at 196608 (+0), Inode bitmap at 196609 (+1)
  Inode table at 196610-197121 (+2)
  32254 free blocks, 16384 free inodes, 0 directories
  Free blocks: 197122-229375
  Free inodes: 98305-114688
Group 7: (Blocks 229376-262071)
  Backup superblock at 229376, Group descriptors at 229377-229377
  Reserved GDT blocks at 229378-229440
  Block bitmap at 229441 (+65), Inode bitmap at 229442 (+66)
  Inode table at 229443-229954 (+67)
  32117 free blocks, 16384 free inodes, 0 directories
  Free blocks: 229955-262071
  Free inodes: 114689-131072
[root@localhost ~]#




이상으로 ext3grep 유틸리티를 사용하여 ext3 파일시스템을 사용하는 파티션에서 삭제된 파일을 복구하는 방법을 공부하였다.
실무에서도 충분히 활용가치가 높은 내용이므로 반드시 한번씩 사용해보기 바라며, 기타 옵션들도 한번씩 사용해 보기 바란다.


-끝-

ext3grep – ext3 복구를 쉽게(지워진 데이터 복구)

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다