Linuxファイルとファイルシステムのリカバリ

前回は、Linuxファイルシステムのサイズ変更とデフラグについて説明した。この連載の最終回となる今回は、消失したファイルをリカバリする方法を解説する。

本稿は、先日刊行された英書『Linux Power Tools』からの抜粋である。

ファイルシステム破損からのリカバリ

コンピュータユーザなら誰もが経験する悪夢、それはファイルシステムが壊れ、データが消失することである。その原因として、システムクラッシュ、ファイルシステム・ドライバのバグ(特に非Linux対応ドライバを使ってLinuxパーティションにアクセスした場合)、低レベルのディスク・ユーティリティの誤用、などが挙げられる。Linuxファイルシステムにはディスクチェック・ツールがあるが、このようなツールには細かい部分に多くの違いがある。

たいていのファイルシステムには、その内容を走査し内部的な整合性をチェックするツールがある。このツールを使えば、壊れたディレクトリ、不正なタイムスタンプ、ディスクの誤った場所を指すinodeなどを発見し、場合によっては修復もできる。Linuxでは、fsckユーティリティが、各ファイルシステム固有チェックツールのフロントエンドの役割を果たしている。これらのチェックツールには、通常fsck.filesystemスタイルの名前が付けられる(filesystemの部分はjfsやext2などのファイルシステム名)。ファイルシステムを手動でチェックする必要がある場合は、fsckを呼び出すか、ファイルシステム固有ユーティリティを直接呼び出す。前者の場合は、fsckを通してファイルシステム固有ユーティリティが呼び出される。

fsckが何をするかは、ファイルシステムによってかなり異なる。たいていはファイルシステム全体の走査が数回実行される。破損のひどいパーティションの場合、問題をすべて修正するためにfsckを何度も実行する必要がある。また、一部のエラータイプでは、fsckから出力される質問に答える必要がある。残念なことに、ファイルシステムをすみずみまで知るエキスパートでない限り、このような質問の大半は意味不明の暗号にしか見えない。幸い、たいていはyesかnoで応答できるので、当て推量で答えられる(一般にデフォルト値にすれば無難な結果が得られる)。

パーティションがひどく壊れた場合に別のパーティションかハードディスクに十分な大きさの未使用領域があれば、fsckを実行する前に、パーティション全体のデータをddでバックアップする。たとえば、dd if=/dev/sda5 of=/dev/hda7を入力すると、/dev/sda5パーティションが/dev/hda7にバックアップされる。こうしておけば、fsckが正常に実行されなかった場合でも、イメージを復元し、他の手段を試すことができる。また、noerror付きでddコマンドを実行すれば、物理的な読み取りエラーが起きているドライブにパーティションをコピーすることも試せる。こうすると、fsckは、読み取りエラーのせいで元のパーティションからリカバリできなかったデータを、コピーしたパーティションからリカバリできるようになる。

システム起動時に、/etc/fstabにあるファイルシステムのエントリに基づいてfsckを自動的に実行するかどうかが決定される。具体的に言えば、ファイルシステム・エントリの最後のフィールドがファイルシステムをいつチェックするか示すコードである。この値が0であれば、起動時にfsckを実行しない。この設定は非Linuxファイルシステムで使われる。ルート(/)ファイルシステムでは値が1であり、これは最初にチェックを行うことを意味する。それ以外のLinuxネイティブのファイルシステムでは、値は常に2である。この値は、ルートファイルシステムの次にチェックを実行するという意味だ。ただし、ブート時のファイルシステム・チェックは、一部のディストリビューションやジャーナリング・ファイルシステムで問題を起こす。具体的に言えば、ファイルシステム・チェックツールが不必要なディスク全体のチェックを強制実行するので、ブートアップのプロセスが遅くなる。そのため、一部のファイルシステム――特にReiserFSやときにはext3fsとXFSで――起動時チェックは無効に設定されている(/etc/fstabの最後のフィールド値が0)。ここに挙げたファイルシステムは、どれもマウント時にジャーナルを自動的にリプレイする機能があるので、ブート時に明示的にファイルシステムをチェックする必要は通常はない。

ファイルシステム・チェックのオプション

メインのfsckプログラムには数種類のオプションがあり、必要に応じて各ファイルシステム固有プログラムに引き渡される。注意が必要なオプションの多くは、ファイルシステムに固有のオプションである。特定のファイルシステムで使えるオプションを次にいくつか紹介する。

スーパーブロックのバックアップ

ext2とext3ファイルシステムではスーパーブロックが使われる。このブロックには、重要なファイルシステム情報が記録される。スーパーブロックの重要性は高いので、ext2とext3ではバックアップ用のスーパーブロックをディスクに保存する。メインのスーパーブロックが壊れた場合は、バックアップの場所を-bで指定してfsck.ext2を使うことができる。バックアップ用スーパーブロックの場所を調べるには、mke2fs -n /dev/fileを入力する(/dev/fileの部分はパーティションのデバイスファイル)。このときに-nオプションを忘れると、mke2fsが新しいファイルシステムを作成し、古いファイルシステムを破壊するので十分に注意すること。

不良ブロックの検出

fsck.ext2に-cオプションを指定すると、ディスク上の物理不良セクタを走査しマーキングすることができる。このオプションを二重に(つまり-cc)指定すると、非破壊式の読み取り/書き込みテストが実行されるので、読み取り専用テストで見逃された問題を発見できる。

強制チェック

通常、たいていのfsckユーティリティは、ファイルシステムがクリーンとマーキングされていれば最小限のチェックしか実行しない。常にチェックを強制するには、fsck.ext2fsck.jfsユーティリティに-fオプションを指定する。reiserfsckでは、–checkオプションを指定すると、エラーはチェックされるが修正は行われない。代わりに–fix-fixableを指定すると、特定のタイプのエラーが自動的に修復される。

ジャーナルの場所

fsck.ext2fsck.jfs、またはreiserfsckに外部ジャーナルの場所を伝えるには、-j journal-locationパラメータで場所を指定する。

ユーザ対話を最小限にする

fsck.ext2fsck.jfs-pオプションを指定すると、表示される質問の数が最小限に減らされる。fsck.ext2では、質問に常にnoで応答する場合に-n、yesで応答する場合に-yオプションを指定できる(noで答えるとfsckはファイルシステムに変更を行わない)。xfs_check-sオプションを指定すると、重大なエラーのみが報告される。ファイルシステムで重要性に差がある複数の問題が起きている場合にこのオプションを使えば、ファイルシステムのマウントを阻害している問題を特定しやすくなる。

スーパーブロックの再作成

reiserfsckプログラムで–rebuild-sbオプションを指定すると、スーパーブロックが再作成される。

ファイルシステム・ツリーの再作成

ディレクトリとファイルのツリー全体を再作成するには、reiserfsck–rebuild-treeオプションを指定する。リスクの大きいオプションだが、うまくいけば大半の問題を修復できる。使用するときは、あらかじめddを使ってパーティションをバックアップすること。

ジャーナルのリプレイを省く

fsck.jfs-oオプションを指定すると、ジャーナルのリプレイが省かれる。ジャーナルそのものが壊れた場合に最適なオプションである。

リブート後に問題が起こらない限り、通常はfsckを使う必要はない。問題が起こった場合は保守シェルに切り替えられ、fsckを手動で実行するようにアドバイスされる。もちろん、実行するしないは自由だが、ディスクの挙動がおかしい―――たとえばファイルが消える、未使用領域が大きすぎたり小さすぎたりする――場合にはアドバイスに従うのが賢明だ。

読み取り/書き込み可能としてマウントされたファイルシステムでは、fsckを実行してはならない。もし実行すると、Linuxが混乱し、さらにファイルシステムの破損が進みかねない。必要であれば、システムをシャットダウンして緊急システムからブートし、マウント解除後のファイルシステムでfsckを実行するか、読み取り専用としてマウントされたファイルシステムで実行する。

ジャーナリング・ファイルシステムは万能薬にあらず

ジャーナリング・ファイルシステムがファイルシステムをエラーから守ると考える人は多いようだ。だが、このファイルシステムの目的は違う。ジャーナリング・ファイルシステムは、クラッシュなどの深刻なエラーが起きた後でファイルシステムをチェックする回数を最小限にするためにデザインされた。ext2fsは、信頼性の高いファイルシステムと評価されている。Linuxのジャーナリング・ファイルシステムも評価は高いが、ext2fs以上に安全だと思うのは間違いだ。

ジャーナリング・ファイルシステムは停電後のシステム起動時間を最短にするので、このファイルシステムを使用するLinuxシステムを正しい手順でシャットダウンしない人がいる。この習慣は危険そのものだ。Linuxはジャーナリング・ファイルシステムへのアクセスにまだキャッシュを使うので、シャットダウンを実行せずにコンピュータの電源を切ると、書き込まれて間がないファイルからデータが消えてしまう。電源を切る前に、常にshutdownユーティリティ(あるいはこの名前でGUIログイン画面に現れるプログラム)を使ってコンピュータをシャットダウンする必要がある。

削除したファイルのリカバリ

おそらくファイルシステムで最も起こりやすい問題は、ファイルを誤って削除することだろう。違うファイルを削除してしまう、削除したファイルが本当は必要だったことに気が付く、こういったミスは頻繁にある。Windowsシステムのユーザは、ファイル復活ユーティリティを使い、最近削除されたファイルをディスクに探しリカバリする作業に慣れているかもしれない。残念なことに、この種のツールはLinuxにほとんどない。ファイルを実際には削除しないで一時的な保管場所に移動し、後で削除できるようにする特殊なユーティリティを使えば、ファイルのリカバリを容易にできる。他に方法がなければ、ファイルをバックアップからリカバリしなければならない。

ゴミ箱ユーティリティ

「削除した」ファイルをリカバリする最も簡単な方法は、ファイルをそもそも削除しないことだ。これがゴミ箱――削除すべきファイルを実際には削除しないで保管しておくツールまたは手続き――の発想である。ゴミ箱の中のファイルは自動的に削除されるか、手動で削除する(ツールや手続きによって異なる)。たいていのユーザになじみがあるゴミ箱ユーティリティの形は――この形はその名の由来でもあるが――KDEやGNOMEなどの多くのGUIデスクトップに表示されるゴミ箱アイコンである。GUIのゴミ箱を使うには、削除したいファイルをアイコンまでドラッグする。基本的にアイコンは、見えない場所に隠された~/Desktop/Trashや~/.gnome-desktop/Trashなどのディレクトリを指すポインタである。ファイルをゴミ箱にドラッグするのは、ファイルをこのディレクトリに移動することに等しい。ファイルの削除を取り消したい場合は、ゴミ箱アイコンをクリックまたはダブルクリックしてファイルブラウザでゴミ箱ディレクトリを開く。後は復活したいファイルをゴミ箱からドラッグするだけだ。通常、ゴミ箱アイコンをマウスの右ボタンでクリックして[Empty Trash]かそれに似た選択肢を選択しない限り、ゴミ箱ディレクトリからファイルは削除されない。

コマンドラインで作業しているときは、たいていrmコマンドを使ってファイルを削除する(rm somefile.txtなど)。このコマンドでは、デフォルトでゴミ箱ディレクトリは使われない。ディストリビューションの種類やデフォルト設定によっては、rmを実行したときにファイルの削除を確認するメッセージが表示されない。rmの安全性を高めるには、削除の確認が行われるように-iオプションを指定する(rm -i somefile.txtなど)。このオプションをデフォルトにしたい場合は、シェル起動スクリプトでエイリアスを作成する。たとえば、bashでこのエイリアスを設定するには、~/.bashrcまたは/etc/profileに次の行を追加する。

alias rm=’rm -i’

-rオプションを使ってディレクトリツリー全体を削除するときや、ワイルドカードを使って多数のファイルを一度に削除するときに、このエイリアスのせいで単調な応答を何度も強いられるかもしれない。その場合は、コマンドを入力するときにrmの完全なパス(/bin/rm)を指定すれば、エイリアスをオーバーライドできる。

ファイル削除の確認は有効な予防策だが、削除したファイルをリカバリする手段ではない。このようなリカバリを簡単に実現するには、GUI環境のゴミ箱を模倣すればよい。つまり、rmを使ってファイルを削除するのではなく、mvを使ってファイルを保管用ディレクトリに移動するのだ。後は、都合の良いときに保管用ディレクトリを空にできる。実際、ゴミ箱のあるGUI環境とコマンドシェルを併用する場合は、同じディレクトリを使える。

rmを使い慣れていると、mvに切り替えるのは難しいかもしれない。また、ファイルをいくつゴミ箱ディレクトリに移動したか忘れやすいので、ディスク領域が知らない間にいっぱいになることもある。この問題を解決するには、ファイルをゴミ箱ディレクトリに移動する簡単なスクリプトをrmに置き換える。このスクリプトは、指定の日付より古いファイルの削除と、ゴミ箱ディレクトリのファイルが一定数を超えた場合のファイルの削除も同時に扱う。あるいは、ゴミ箱ディレクトリのファイルを定期的に削除するcronジョブを作成することもできる。このようなスクリプトの一例がsafermだ。safermや同類のスクリプトを使うには、通常のrmに代わるスクリプトをインストールし、rmの代わりにこのスクリプトを呼び出すエイリアスを作成するか、スクリプトを直接呼び出すことが必要だ。たとえば、次のようなエイリアスを使用する。

alias rm=’saferm’

safermではファイルの削除を確認するメッセージがデフォルトで表示されるが、これを省くにはread answer行をread answer=Aに変更し、その直前にあるecho行をコメント化する。safermでは、ゴミ箱ディレクトリとしてユーザのホームディレクトリの~/.trashを使う。「削除した」ファイルをリカバリする必要がある場合は、ファイルを~/.trashから移動すればよい。safermにはゴミ箱を自動的に空にする機能はないので、本物のrmを使って自分で削除を行うか、cronジョブを作成して削除する必要がある。

ファイルリカバリ・ツール

Linuxで利用できるファイル復活ユーティリティは極めて少ない。ユーザは本当は削除したくないファイルを削除すべきではなく、もしそうしてしまった場合はバックアップから復元すべきである、というのがLinuxの思想だ。とはいえ、ピンチのときに、誤って削除したファイルをリカバリするために試せるトリックがいくつかある。

そういったトリックの1つが、たいていのLinuxディストリビューションに含まれているrecoverユーティリティだ。残念ながら、このツールには欠点がある。ext2fs向けにデザインされたツールなので、ほとんどのジャーナリング・ファイルシステムには使えない(ext3fsには使えるかもしれない)。また、たとえパーティションが小さくても、実行に時間がかかる。recoverを実行すると、Webブラウザやメールクライアントなどのネットワーク・プログラムがたびたびクラッシュするのも問題だ。個人的な経験から言えるが、リカバリがうまくいかないことも多い。たとえば、recover /dev/sda4と入力してファイルを/dev/sda4からリカバリしようとすると、しばらくの間アクセスが激しく行われ、CPUタイムが大量に消費され、Terminated(終了)のメッセージが表示される。結論を言えば、recoverは信頼できるツールではなく、他にどうしようもないときに試してみる程度のものだ。もし試してみる場合は、不要なネットワーク対応プログラムを先にシャットダウンすることをお勧めする。

ファイルをリカバリするもう1つのトリックとして、grepを使ってファイル内のテキストを検索する方法がある。この方法はおそらくテキストファイルにしか通用しないだろうし、ファイルの一部、またはテキストやバイナリのゴミに囲まれたファイルが返されることもある。たとえば、次のようにコマンドを入力する。

# grep -a -B5 -A100 “Dear Senator Jones” /dev/sda4 > recover.txt

このコマンドは、Dear Senator Jonesというテキストを/dev/sda4下に探し、見つかったテキストの直前の5行(-B5)と直後の100行(-A100)を返す。リダイレクト演算子によって結果がファイルrecover.txtに保存される。このコマンドの実行にはraw型ディスクデバイス全体の走査が伴うので、おそらく時間がかかる(多少スピードアップするには、リダクレクト演算子を省いて実行し、xtermに表示された結果行をテキストエディタにカットアンドペーストする。この方法を使うと、ファイルが見つかった時点でCtrl+Cを押して処理をキャンセルできる。他に、出力をファイルにコピーする新しいシェルをscriptで起動する方法もあるが、この場合はテキストをエディタにコピーする必要はない)。このトリックは、ファイルシステムの区別なく使用できる。ただし、ファイルが断片化していると、その一部しか返されない。ファイルの行数を的確に見積もれないと、ファイルの一部しか返されないか、ファイルの範囲を超えた領域が――おそらくファイルの前後やときには途中にバイナリデータが含まれた状態で――返される。

バックアップからのファイル復元

非常時のリカバリ手続き――稼動システムのほとんどかすべてをバックアップから復元すること――は、ディスク障害、セキュリティ侵害、深刻な管理上の不手際の際に便利である。また、システムバックアップは削除したファイルの復元にも非常に有効だ。誤って削除したファイルをバックアップから復元できる。この方法の欠点は、最後の定期システムバックアップの時点で目的のファイルが存在していなければ意味がないことだ。バックアップがたまにしか行われないと、ファイルがバックアップに含まれていない可能性がある。たとえバックアップを毎日実行していても、作成したファイルをすぐに削除した場合はおそらく復元できない。この種の削除に対処するには、ゴミ箱が最適である。

たとえば、tarを使ってテープにバックアップを保存したとする。このバックアップからファイルをリカバリするには、–extract (-x)コマンドを使う。たいていは–verbose (-v)オプションも指定して、目的のファイルが復元されたことを示す通知を出力し、–file (-f)を使ってテープデバイスファイルを指定する。また、復元するファイルの名前も指定する必要がある。

# tar -xvf /dev/st0 home/al/election.txt

このコマンドは、ファイルhome/al/election.txtを/dev/st0テープデバイスから復元する。このコマンドで注意すべき点を次に説明する。

アクセス権

コマンドを実行するユーザは、テープデバイスへの読み取り/書き込みアクセス権を持つ必要がある。また、ファイルを復元するディレクトリ(たいていはカレントディレクトリ)への書き込みアクセス権も必要となる。したがって、通常はrootでこのコマンドを実行するが、システムによっては他のユーザが十分な権限を持っている場合もある。root以外のユーザがコマンドを実行すると、復元されるファイルの所有権とアクセス権が変更される。

ファイル名の記述

前掲のコマンドでは、先頭のスラッシュ(/)を省いて目的のファイル名(home/al/election.txt)を記述した。こうするのは、tarがこのスラッシュを付けずにファイルを書き込むので、復元するファイルを指定するときもスラッシュは必要ないからだ。少数のバックアップ作成ユーティリティや手続きではファイル名の先頭に./が付けられる。このような場合は、ファイルを復元するときに./を付ける必要がある。

ディレクトリの復元

通常、tarは、ファイルをカレント・ワーキングディレクトリに復元する。したがって、前掲のコマンドを/rootで入力すると、/root/home/al/election.txtファイルが作成される(このファイルがテープにあれば)。こうする代わりに、ファイルを空のサブディレクトリに復元し、それを本来の目的の場所に移動することをお勧めする。この手順を守れば、目的のファイル名をミスタイプし、古いファイルで現在のファイルを上書きしてしまったり、極端な場合にLinuxシステム全体をバックアップで上書きしてしまう事故を防止できる。

残念なことに、tarでは、パス名を含む完全なファイル名を指定しないとファイルを復元できない。正確なファイル名がわからない場合は、tar tvf /dev/st0を入力してテープのディレクトリを取得する(必要に応じてテープ名は実際の名前と置き換えること)。結果をパイプしてlessまたはgrepに渡して正確なファイル名を検索するか、ファイルにリダイレクトしてエディタで検索できる。

バックアップ時にテープにファイルのレコードを残しておくと、復元するときの検索が楽になる。–verboseオプションを指定し、結果をファイルにリダイレクトすればこのトリックを使える。一部の増分バックアップ手続きでは、バックアップの内容に関する情報も自動的に保存される。市販のバックアップツールBackup/Recover Utilityなどには、ファイルのインデックスをテープに保存する機能がある。このインデックスを利用すれば、テープをすばやく走査し、リカバリするファイルを選び出せる。

まとめ

Linuxは、他のOSと同じように、ファイルシステムに基づいて成り立っている。ext2ファイルシステムは、長年Linuxの標準ファイルシステムだったが、2.4.xカーネルの開発が進む中で新しいジャーナリング・ファイルシステムが標準装備として次々に追加されている。このようなジャーナリング・ファイルシステムで提供されるオプションには、種類の異なるファイルが占めるディスク領域、ACLのサポートなど、微妙な違いがある。たいていのシステムは、どのLinuxファイルシステムでも動作するが、ディスクのパフォーマンスが死活問題となる場合は、さらにオプションを調査し、ニーズに最適なものを選び出す必要がある。また、ファイルシステムを最適化する方法も、ファイルシステム作成時のオプションからファイルシステムのデフラグ、サイズ変更までさまざまである。残念なことに、ファイルシステムは常に高い信頼性で動作するわけではない。ときには、ファイルシステム破損の修復を迫られる。この作業に役立つ各種のツールが用意されている。また、ユーザが誤ってファイルを削除することもあり、そういったファイルをリカバリするのは容易ではないが、ゴミ箱ユーティリティを使ってアクシデントに備え、定期バックアップを実行することで、リカバリ作業の負担を大きく軽減できる。