MBRのバックアップ

以下のサンプルには、ファイルシステムを通さず、HDDに対して直接データを書き込むものがある。下手をするとファイルシステム等の内容を破損して、最悪の場合システムが立ち上がらなくなることもあるので、実行する場合は自己責任はもちろんのこと、細心の注意を払ってほしい。

MBRはブートストラップローダやパーティションテーブルが格納されているので、誤って消してしまうとシステムは立ち上がらなくなってしまう。

ブートストラップローダは、再度インストールしなおすこともできるが、パーティションテーブルが失われてしまったら、短時間でシステムを普及するのは難しい。HDDのデータの海の中から各パーティションの先頭セクタとその終わりを探すのは時間と根性を必要とする作業となる。
従って、MBRは必ずバックアップしておくべきだろう。ところが、ネット上でMBRのバックアップに関した記事を見ていると

MBRはddコマンド使ってバックアップできる。
# dd if=/dev/sda of=/mbr.img bs=512 count=1

で説明が終わっている記事が多い。気が利いている記事でも「フロッピーにコピーしておいた方がいいだろう」程度のものが多い。これは「いいだろう」ではなく「しなけらばならない」ではない?と思う。なぜなら、HDDのファイルシステムにファイルとしてMBRのバックアップを取っておいても、イザと言う時に役に立たないからだ。パーティションテーブルが破損していたら、HDDをファイルシステムとしてアクセスすることができなくなる。どこがファイルシステムの先頭だか分からなくなるからだ。

そこで、ここでは「ddコマンドを使えばできる」レベルの話ではなく、どのように(もしくはどこに)MBRをバックアップすればイザと言う時に便利か考えてみた。

補助メディアにバックアップする

フロッピーディスクUSBメモリにバックアップするのが一般的かと思う。例えば次のようにすれば簡単にバックアップが可能である。

# dd if=/dev/sda bs=512 count=1 of=/media/USB/mbr_backup.img

(ここで、“/media/USB/”はUSBメモリがマウントされているディレクトリを想定している。ディストリビューションやシステムの設定、USBのID等によって異なるので、このパス名は自分のシステムにあわせて解釈してほしい。)
障害時にバックアップを元に戻すには、CD/DVDからブートするISO Linuxを立ち上げ次の様にすれば良い。

# dd if=/media/USB/mbr_backup.img bs=512 count=1 of=/dev/sda

ただし、この方法はバックアップファイルを格納したメディアの管理がいま一つ面倒なところが問題。どのメディアに格納したのか、(複数のマシンがある場合は)どのファイルなのか、また、USBなどは使いまわすので、ついついバックアップファイル消してしまうこともある。

第1セクタにコピーする

一応、書いてはみたが、この方法は余りお勧めできない。この方法より次に紹介している「最終セクタにコピーする」の方が良いと思う。色々とGRUBのインストールの実験をしていたら1.5次ローダを第1セクタから23セクタまで書き込んでいたケースがある。(「LinuxにおけるgrubによるMBRの修復方法」参照)

MBRはHDDの第0セクタに置かれるが、そのコピーを第1セクタへコピーしておく、という方法。第1パーティションは(なぜか)トラック境界に合わせたところから始まるので、MBRの次のセクタ(=第1セクタ)から始まるのではなく(システムによって異なるが)大抵の場合、CHS方式で第1シリンダ/第1ヘッド/第0セクタから始まる。LBA方式で言えば第63セクタから始まる。つまり第1〜62セクタは使われない。そこで、第1セクタに第0セクタのMBRのバックアップをコピーして置く方法である。
次のコマンドでMBRをコピーできる。

# dd if=/dev/sda bs=512 count=1 of=/dev/sda seek=1

このバックアップを元に戻すのは、ISO Linux等を立ち上げ、次のコマンドでMBRを修復する。

# dd if=/dev/sda bs=512 count=1 skip=1 of=/dev/sda

この方法の問題点は、全てのLinux、全てのOS、全てのシステムで第1〜62セクタを使わないという保証がない。他のOSとマルチブートの環境では気をつけた方がいい。また、Linuxだけの単独インストールでもディストリビューションによっては使えないかも知れない。実際、第1〜62セクタを使うような構成に遭遇したこともある(特殊なケースでGRUBが2次ローダをここに置くことがあるようだ)。更に特殊なアプリケーション(例えばバックアップソフト、暗号化ソフト、デフラグツールなど)がこのエリアを使わない保証もないので、この方法を使うのであれば、第1セクタが使われていないことを確認の上、自己責任でお願いしたい。(こんなルートキットもあるそうだ⇒MBR感染機能付きルートキット「StealthMBR」
もう一つ、この方法の問題点はバックアップがMBRのすぐ隣(もしくは近辺)のセクタにあるため、MBRが破損される場合にパックアップのセクタまで破損してしまう可能性がある。

一方、この方法の良い点は、バックアップメディアの管理をする必要がないこと、HDDの設定を変更しなくても利用できること、だと思う。

最終セクタにコピーする

上の方法は全てのソフトウェアで第1セクタを使わない保障がないことである。それを回避するためにはバックアップデータを格納するパーティションを設定れば良いのだが、基本パーティションは4つしか設定できないのに1つをバックアップ用に使うのはもったいない。また何より、MBRに障害があるケースではパーティションテーブルも壊れる可能性が高く、バックアップがHDD上の何処にあるのか分からなくなってしまう。

そこで、最初にシステムをインストールするとき(正確にはHDDのパーティションを設定する時)に最終シリンダをどのパーティションにも属さないようにパーティションを設定する。例えば、1044シリンダあるHDDの場合(第0〜1043シリンダ)、第1043シリンダをどのパーティションにも属さないように設定する(特に最後のパーティションに含まれないように設定する)。例えば、Fedoraのインストール・ユーティリティでディスクのパーティションを“カスタムレイアウト”で行い、次のように“空き”の領域を設けておく。(注意:Fedoraのインストールツールは先頭シリンダは第0シリンダではなく第1シリンダと定義しているので、最終シリンダは1043シリンダではなく1044シリンダになる。シリンダはCHS方式でもLBA方式でも0から始まると思っているのだが....。)

この1シリンダはどのパーティションにも属さないので、ここを使うアプリケーションはほぼ無いと思われる。この1シリンダ約8MB(=63セクタ×255ヘッド×512バイト)はMBRを格納するには大き過ぎ、ちょっと無駄のような気もするが、最近のHDDは大容量化しているので、イザと言う時の保障としては安いものだと思う。なお後述するが、物理ジオメトリと論理ジオメトリが異なる場合、ユーティリティで最後のパーティションをきっちり最終シリンダまで使い切ったとしても、なお端数のセクタ(=どのパーティションにも属さないセクタ)が存在する。その場合は、わざわざ1シリンダを使わなくても、その端セクタ(“は”セクタ)を利用してMBRをバックアップすることができる。(物理ジオメトリと論理ジオメトリについては「ホスト上のHDDイメージファイルをゲストマシンでマウントして使う」も関連トピック。)

さて、バックアップするには次のコマンドを使う。

# dd if=/dev/sda bs=512 count=1 of=/dev/sda seek=“HDDの総セクタ数−1”

MBRの修復はISO Linux上で次のコマンドを実行する。

# dd if=/dev/sda bs=512 count=1 skip=“HDDの総セクタ数−1” of=/dev/sda

ここで“HDDの総セクタ数−1”の“総セクタ数”は fdiskコマンドもしくは hdparmコマンドで確認できる。例えば次のようになる。

[root@fedora-8 ~]# hdparm -g /dev/sda

/dev/sda:
 geometry      = 1044/255/63, sectors = 16777216, start = 0
[root@fedora-8 ~]# 

さて、ここで先ほど書いた「端セク」(端数のセクタ、はせく)について触れておく。この例では63セクタ、255ヘッド、1044シリンダの論理ジオメトリを使っているが、これだと総セクタ数は63×255×1044=16,771,860セクタになる筈。しかしhdparmコマンド(もしくはfdiksコマンド)で表示した総セクタ数は16,777,216で5,356セクタ少ない。これは物理ジオメトリと論理ジオメトリが異なるために、論理ジオメトリには含むことができない端数が生じるためだと思う。つまり、論理的には16,771,860セクタしかない筈だが、実際には16,777,216セクタが存在し、5,356セクタは(基本的には)このシステムでは使用できないことになる。そこで、この端セクにMBRのバックアップを格納すれば良いのではないか。(なお、物理ジオメトリと論理ジオメトリが同じ場合やたまたま公約数になっていて割り切れる場合は端数が生じないので、その場合は1シリンダを未割当シリンダとしておく必要がある。新しいシステムをインストールする時は、一度インストールして、ジオメトリの差異と端セクの存在を確認しておくとよい。)

実際にバックアップしてみたのが以下の例となる。まず、最終セクタが空であることを確認する。

[root@fedora-8 ~]# dd if=/dev/sda bs=512 skip=16777215 | hexdump -C
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.00269636 s, 190 kB/s
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200
[root@fedora-8 ~]# 

次にMBR(先頭セクタ)を最終セクタへコピーする。

[root@fedora-8 ~]# dd if=/dev/sda bs=512 count=1 of=/dev/sda seek=16777215
1+0 records in
1+0 records out
512 bytes (512 B) copied, 4.1466e-05 s, 12.3 MB/s
[root@fedora-8 ~]# 

先程と同じコマンドでMBRが最終セクタに書き込まれたかを確認する。

[root@fedora-8 ~]# dd if=/dev/sda bs=512 skip=16777215 | hexdump -C
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000277876 s, 1.8 MB/s
00000000  eb 48 90 10 8e d0 bc 00  b0 b8 00 00 8e d8 8e c0  |.H..............|
00000010  fb be 00 7c bf 00 06 b9  00 02 f3 a4 ea 21 06 00  |...|.........!..|
 :
 :
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200
[root@fedora-8 ~]# 

この方法の良い点は、バックアップメディアの管理をする必要がないこと、MBRとそのコピーがHDD上正反対の位置にあるので、同時に破損する可能性が少ないこと等である。短所としては、予めコピーを格納する場所を確保しないとならないので、運用に入ってしまっているシステムでは適用が難しいことだろうか(ただし、端セクタが存在する場合は可能)。

なお、この方法はシステムが通常ではアクセスしないセクタがあればどこでも可能で、たとえばパーティションパーティションの間に、どこのパーティションにも属さないセクタを置いておくこともできる。が、MBRパーティションテーブルが壊れた場合、どこがパーティションの境か分からなくなるので、一番無難なのは最終セクタを利用する方法だろう。

同様の理由で、各ファイルシステムの先頭にMBRをコピーする方法もあまりお勧めできない。ファイルシステムの種類にもよるが、ファイルシステムの先頭には予備のブート領域を持つものもあり、そこにMBRをコピーすることも可能だとは思うが、肝心のパーティションテーブルが壊れては、どこがファイルシステムの先頭だか分からなくなってしまう。

ただし、この方法はEFIを既に採用しているシステムには使えない。というか、EFIパーティションテーブルのバックアップとして最終セクタを使っている。まぁ、最終セクタを使うっていうのは誰でも考えつきそうなことだし。(詳しくは「GUIDパーティションテーブル - Wikipedia」あたりを参照)