Ext3 ファイルシステムで削除したファイルを復元について
うっかりファイルを消してしまったりすることは、よくあると思います。
いろいろ事情があって、ext3 ファイルシステムで削除したファイルの復元について、半日ぐらい調べていました。 恥ずかしながら ext2 の場合も同じだろうと ext2 の場合の復元方法を一生懸命テストしたり、古い文書やメーリングリストの議論に惑わされたりしながら、やっと Linux ext3 FAQ のなかの ext3 の開発者のひとりの引用を読んで調査が終了しました。
Q: How can I recover (undelete) deleted files from my ext3 partition?
つまり ext2 の場合は、ファイルを削除するとき inode を "deleted" としるしをつけるだけなので、 debugfs コマンドの lsdel で削除された inode の一覧を得ることができるし、その削除された inode 番号に対して debugfs コマンドの dump でファイルの中身もだいたい復元できることが期待できます。
# debugfs -R lsdel /dev/sdb1 > /tmp/lsdel.lst
# vi /tmp/lsdel.lst <間違って削除した日時とかで該当しそうな行だけ残す>
# awk '{printf "dump <%d> /tmp/undel.%d\n", $1, $1}' /tmp/lsdel.lst > /tmp/debugfs.cmd
# debugfs -f debugfs.cmd /dev/sdb1
しかし ext3 の場合は、ファイルを削除すると、inode からデータブロックへの参照をきれいにクリアするので inode からデータブロックをたどることができません。唯一の望みは grep でファイルの断片を見つけることぐらいとのことです。
1. まず、ブロックデバイスでもディスクイメージでもいいのですが、 dumpe2fs コマンドなどでブロックサイズを調べます。 この ext3 ファイルシステムのブロックサイズは 4096 バイトでした。
# dumpe2fs /dev/sdb1
...Block size: 4096
...
2. grep の -b オプションでキーワードがマッチしたオフセットを表示するようにして、なにかファイルに保存しておきます。
# grep -a -b 'BEGIN RSA PRIVATE KEY' /dev/sdb1 | awk -F: '{print $1}' > list
追記: この grep での検索にはいくつか落し穴があったので、こちらのエントリも参照してください。
3. キーワードが含まれているブロックをファイルに保存します。
# cat list | while read i; do
dd if=/dev/sda1 of=$i.data bs=4096 count=1 skip=$(($i/4096))
done
4. 見つかったブロックの中身をひとつひとつチェックして削除したファイルを地道に探します。
メールとか自分で書いたプログラムとかのユニークなキーワードをおぼえていたら削除したファイルでもなんとか復元できるかもしれません。ファイルサイズがブロックサイズより大きくても、 ext3 はなるべく近くのブロックに割り当てるようにしているのでファイルシステムがひどく断片化していなければ、その辺の連続したブロックに同じファイルの内容が保存されている可能性が高いと思います。実際、ある 50KB ほどの削除してしまったテキストファイルを多分無傷で復旧できたということだけ伝えておきます。



コメント