extundeleteによる削除済みファイルの復元方法

概要 コマンドラインからrmコマンドで削除したファイルの復活方法を解説します.
検証環境 Ubuntu 12.04 x86_64
ファイルシステム: ext4
備考 ここで説明する方法はext4またはext3のみに適用可能なものです.ext2ではmc(GNU Midnight Commander)というファイラーの“Undelete files”機能を使うことで回復できる可能性があります.
参考:@IT 削除したファイルを復活するには

誤ってファイルを削除した直後にすべきこと

削除したファイルを格納していたパーティションをunmountするかread-onlyにしてください.[備考: これを容易にするため,OS本体とユーザーデータを格納するディレクトリ(homeディレクトリ)を別パーティションにしておくことをおすすめします.ルートディレクトリと/homeが同じパーティションに格納されている場合,パーティションのアンマウントが難しくなり,ファイルを回復できる見込みは薄くなります.]

/homeunmountする場合,下記のとおりです.カレントディレクトリが/homeの下になっていると“devide is busy”エラーになってしまいますので,この例では先にカレントディレクトリをルート(/)に移動しています.

$ cd /
$ sudo unmount /home

/homeをread-onlyにする場合,下記のとおりです.2つ目のmountコマンドはremountしたパーティションがread-onlyになっていることを確認するためのものです.“ro”と表示されればread-onlyになっています.read-onlyになっていることを確かめるために実際に書き込んでみるというような勝負をすべきではありません.

$ sudo mount -o remount,ro /home
$ mount
/dev/sdc2 on /home type ext4 (ro,errors=remount-ro)

ここまで実施すれば,ファイルが(ここで紹介する方法で)復活できるか,そうでないかは確定します.[復活させたいファイルが画像ファイルや音声ファイルなど,“ある種の特徴”をもっている場合,ディスク上の全セクタを走査して“ある種の特徴”に合致するデータを見つけ出すというヒューリスティックな方法で復活できる可能性があります.詳しくは“PhotoRecによる削除済みファイルの復元”を参照してください.]

復元: extundeleteの実行

復元したいファイルが/dev/sdc2に格納されていた場合,下記のように実行します.

$ sudo extundelete /dev/sdc2 --restore-all
WARNING: Extended attributes are not restored.
Loading filesystem metadata ... 14905 groups loaded.
Loading journal descriptors ... 32420 descriptors loaded.
Searching for recoverable inodes in directory / ... 
7232 recoverable inodes found.
Looking through the directory structure for deleted files ... 

復元したファイルはデフォルトではカレントディレクトリのRECOVERED_FILESディレクトリに格納されますので,十分な容量があるディレクトリで実行してください.この例では/dev/sdc2上の復活可能な削除済みファイルすべてを復元しています.それでは多すぎる場合,オプションで,ある時刻以降に削除したファイルのみ,あるパスの下にあったファイルのみを復元するように指定してください.
日時指定の例
$ date --date='2012-01-01 00:00' '+%s'
Sun Jan  1 00:00:00 JST 2012
$ sudo extundelete /dev/sdc2 --after `date --date='2012-01-01 00:00' '+%s'`
パス指定の例 sudo extundelete /dev/sdc2 --restore-files 'home/hatai/f.txt'

より深い理解のために(上級者向け)

ext4/ext3上のファイルの復元はext2の場合より格段に難しいです. ユーザーからファイル削除の指示がでるとファイル本体を格納していたブロックやそのinode,ディレクトリエントリに“未割りあて”(unallocated)のマークがつきますが,ext2ではinode上に記録されている,ファイル本体を格納していたブロックのアドレスやファイルサイズの情報は(まだその時点では)残っています. しかし,ext4/ext3では,inode上のファイル本体を格納していたブロックのアドレスやファイルサイズの情報がすべてクリアされてしまうのです.したがって,未割りあてになっているinodeを強引に読んで目的のファイルを復元してしまうという方法がとれません.

そのため,ext4/ext3では,(1)ファイルの特性を使って復元するか[例えばJPEGファイルは仕様上0xFFD8ではじまって0xFFD9で終わることがわかってるため,この情報を頼りに復元することができます],(2)ジャーナルのログエントリを利用して復元するかの2通りしかなく,かつ,いずれもext2の場合より復元できる確率も低く,精度も悪くなります.

(1)の手法をつかった復元方法については“PhotoRecによる削除済みファイルの復元”を参照してください.ここでは,extundeleteが使っている(2)のジャーナルを解析による復元方法を説明します(といってもたいした役にはたちませんが…).

debugfsで“ls -d”コマンドを実行すると,現在存在するファイル(allocated files)と削除済みのファイル(unallocated files)の情報が得られます.debugfsで見たときに<>で囲まれて表示されるのが削除されたファイルのinodeです.

$ sudo debugfs /dev/sdc2
debugfs 1.42 (29-Nov-2011)
debugfs:  ls -d
 2  (12) .    2  (12) ..    11  (20) lost+found    18874369  (16) mirror   
 61865985  (32) bak   <14> (20) .f.txt.swp    12  (4004) f.txt   
(END)

ジャーナル ログをみるにはlogdump -iを使います.ここでは削除済みの<14>のログ エントリをみたいので下記のように指定します.

debugfs:  logdump -i <14>
Inode 14 is at group 0, block 1057, offset 1664
Journal starts at block 0, transaction 13933

上記のように素っ気なく表示された場合は,もうダメです.何も情報がなくて,これ以上進めないでしょう. 下記のように表示された場合は,いちおう情報は残っているのですが,この場合もinodeのi_extra_isizeが不正になっているため,過去のBlocksが取得できず,やはりダメです.

debugfs:  logdump -i <14>
Inode 14 is at group 0, block 1057, offset 1664
Journal starts at block 1, transaction 13934
  FS block 1057 logged at sequence 13934, journal block 3 (flags 0x2)
    (inode block for inode 14):
    Inode: 14   Type: bad type        Mode:  0034   Flags: 0x0
    Generation: 0    Version: 0x00010000:00000000
    User:     0   Group:     0   Size: 0
    File ACL: 0    Directory ACL: 0
    Links: 0   Blockcount: 0
    Fragment:  Address: 0    Number: 0    Size: 0
     ctime: 0x00000000:08000000 -- Thu Jan  1 09:00:00 1970
     atime: 0x00000000:4dc24c5f -- Thu Jan  1 09:00:00 1970
     mtime: 0x4e2f0607:4dc24c5f -- Wed Jul 27 03:23:03 2011
    crtime: 0x4dc24c5f:00000000 -- Thu May  5 16:06:07 2011
Size of extra inode fields: 33152
invalid inode->i_extra_isize (33152)
    Blocks:  
No magic number at block 9: end of journal.

私が試してみた限りでは,extundeleteによる復元の成功率は極めて低いものでした. ext4のジャーナルの理解が不十分なので結論は出せませんが,extundeleteによる復元できる可能性は低いと考えて良さそうです.

参考: 少しひねったアプローチ

特殊な例になりますが,削除したファイルを開いているアプリケーションが残っている場合,そのアプリケーションがつかんでるファイルをコピーすることでファイルを救出する方法もあります. 例えば,動画が収録されているf.isoというファイルを再生中に,f.isormした場合,下記のようにlsof(list open files)で開いているファイルの情報を得て,コピーすることができます. この例では,gvfsd-arcというプログラムが開いている/home/unsync/f.isoをコピーしています.プロセス番号が10764,ファイル ディスクリプターが9なので,/proc/10764/fd/9が目的のファイルになっています.

$ lsof |grep iso
gvfsd-arc 10764      hatai    9u      REG               8,34 2340454400       13 /home/unsync/f.iso (deleted)
$ cp /proc/10764/fd/9 x.iso

Links

[1] extundelete
[2] PhotoRecによる削除済みファイルの復元
[3] Why Recovering a Deleted Ext3 File Is Difficult...
[4] ext4の徹底調査(by IBM)

はたいたかし
2012-05-27
Home > Linux > extundelete