検索
特集

削除したファイルをlsofで復元するLeverage OSS

ファイルを間違って削除してしまったときのショックはよく分かる。誰にでもあり得る失敗だ。だが、失われたファイルを取り戻す簡単な方法はある。しかも、それはどの標準Linuxシステムでも使える方法だから、覚えておいて絶対に損はない。

PC用表示 関連情報
Share
Tweet
LINE
Hatena
SourceForge.JP Magazine

 例えば、あなたが午後いっぱいを費やして製作したオーディオファイルの再生を楽しみながら、「やあ、こいつはすごい音だ! こっちに移動しておくとしよう」と思ったとする。そのとき、潜在意識が違和感を唱えるのだ。「ええと、mvだっけ、rmじゃないのか?」……やっちまった。そのショックはよく分かる。誰にでもあり得る失敗だ。だが、失われたファイルを取り戻す簡単な方法はある。しかも、それはどの標準Linuxシステムでも使える方法だから、覚えておいて絶対に損はない。

 簡単に説明すると、Linuxファイルシステム上にあるように見えるファイルは、実際はinodeへのリンクにすぎない。inodeには、ファイルのあらゆるプロパティ(アクセス権や所有権など)のほか、ファイルの中味が実際に存在するディスク上のデータブロックのアドレスも記録される。rmコマンドでファイルを削除すると、ファイルのinodeを指すリンクは削除されるが、inodeそのものは削除されない。削除した時点で、ほかのプロセス(オーディオプレーヤーなど)でファイルがまだ開かれている場合もある。このようなプロセスがすべて終了し、すべてのリンクが削除されるまで、inodeとそれに関連づけられたデータブロックが書き込みの対象となることはない。

 このように実際のファイルが削除されるまでタイムラグがあることは、素早い復元の成功にとって重要なポイントだ。ファイルを開いているプロセスがあれば、データはまだ存在する。例えディレクトリリストからファイルが消えてしまっていても。

 ここで、Linuxプロセス擬似ファイルシステム、つまり/procディレクトリの出番となる。システムに存在するプロセスは、自分と同じ名前のディレクトリをこの/procディレクトリ下に持つ。そのディレクトリにはさまざまなものが入っているが、その1つであるfd("file descriptor")サブディレクトリにはプロセスで開かれているすべてのファイルへのリンクが含まれる。ファイルをファイルシステムから削除した後も、データのコピーは以下の場所にある。

/proc/process id/fd/file descriptor


 どこに行けばよいかは、ファイルを開いているプロセスのIDとファイル記述子を取得すると分かる。これらの情報は、lsofで取得が可能だ。lsofという名は"list open files"(開いているファイルをリストする)に由来する(実際にはそれ以上の機能があり、便利なツールなのでほとんどのシステムに標準でインストールされる。インストールされていない場合は、最新のバージョンを作者から直接入手できる)。

 lsofから情報を取得すれば、データを/procからコピーできる。これで終わりだ。

 以上の操作は実習してみるのが一番分かりやすいだろう。まず、削除してから復元するサンプルのテキストファイルを作成する。

$ man lsof | col -b > myfile


 次に、今作成したファイルの内容を表示してみよう。

$ less myfile


 lsofの長大なmanページが、lessによってプレーンテキスト形式で出力される。

 次にCtrl+Zキーを押して、lessの出力を中断する。シェルプロンプトで以下のコマンドを実行して、ファイルが存在することを確認する。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 よし、確かに存在する。さて、次に大失敗をやらかすことにしよう。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 ファイルは消えた。

 この時点では、ファイルを使用しているプロセスは残しておく必要がある。そうしないと、ファイルが本当に削除され、トラブルが深刻になる。このデモで使っているバックグラウンドのlessプロセスは、killするかシェルを終了しない限りどこにも行かないが、ビデオやサウンドのファイルを再生している場合は、ファイルを削除したことに気が付いた時点ですぐにアプリケーションの再生を一時停止するか、ほかの手段でプロセスをフリーズする必要がある。そうすれば、ファイルの再生がやがて終了し、プロセスが終了することを避けられる。

 さて、ファイルの復元に取りかかろう。最初に、lsofの出力を見てみる。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 1列目はプロセスに関連付けられたコマンドの名前、2列目はプロセスID、4列目の数字はファイル記述子である("4r"の"r"は"regular file"、つまり通常のファイルを意味する)。この出力から分かるのは、プロセス4158がまだファイルを開いていること、ファイル記述子が4であることだ。後は、この情報を/procからコピーする方法さえ分かればよい。

 ファイルを復元するのだから、cpで-aフラグを使えばいいと思うかもしれない。だが、実際にはそれをしないことが重要なのである。もしこのコマンドを実行すると、ファイル内のリテラルデータをコピーするのではなく、元のディレクトリにリストされていた、今は壊れてしまったファイルへのシンボリックリンクをコピーすることになる。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 そこで、代わりに単純な古きcpでコピーする。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 最後に、目的が達成されたことを確認する。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 cmpで不一致は報告されない。復元はまごうことなき本物である。

 余談だが、失われたファイルの復元以外にも、lsofにはたくさんの便利な機能がある。

Copyright © 2010 OSDN Corporation, All Rights Reserved.

ページトップに戻る