HDDイメージファイルをマウントして使う方法
小容量HDDの内容をddコマンドで物理イメージを丸ごとバックアップしたファイルがあった。
[root@linux ~]# dd if=/dev/sdb of=hdd.img bs=512M
このHDDのイメージファイルはLinux上でマウントしてファイルシステムとして利用できる。(追記:この応用としてVMwareの仮想ディスクをホスト上でマウントして使うという応用もある。「VMwareの仮想ディスクをLinuxでマウントして使う」参照。)
■ mountコマンドのオフセット指定でマウントする
[root@linux ~]# ls /mnt ;: ←/mntの下は空 [root@linux ~]# mount -o loop,offset=31744 hdd.img /mnt ;: ←イメージファイルをマウントし [root@linux ~]# ls /mnt :; ←ファイルシステムとして使う bin dev home lost+found mnt poweroff root selinux sys usr boot etc lib media opt proc sbin srv tmp var [root@linux ~]#
ここでオフセットとしてゲタ上げをしているのはマウントしたいパーティションのアドレスになる。HDDの中には複数のパーティションを設定して、それぞれを別々のミニディスクと使えるが、そのパーティションのHDD内での位置(HDDの先頭から何バイトずれたところから始まっているか)である。従って、パーティションのHDD内における位置によって異なる。パーティションの情報はHDDの先頭のMBR(Master Boot Record)という部分に記録されているので、それを解読する必要がある。(MBRに関しては「LinuxにおけるMBRのまとめとバックアップ方法」等を参照。)しかし、解読にはMBRの構造に詳しくないと中々難しいのでパーティションテーブルの情報を確認するためには fdiskコマンドを使う。(fdiskコマンドの拡張命令を使う。)
[root@linux ~]# fdisk hdd.img You must set cylinders. You can do this from the extra functions menu. Command (m for help): x Expert command (m for help): p Disk hdd.img: 125 heads, 62 sectors, 0 cylinders Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID 1 80 1 1 0 124 62 1017 62 7889438 83 2 00 0 0 0 0 0 0 0 0 00 3 00 0 0 0 0 0 0 0 0 00 4 00 0 0 0 0 0 0 0 0 00 Expert command (m for help): q [root@linux ~]#
また、上記のようにインタラクティブモードではなくコマンドモードで各パーティションのスタートセクタとセクタ数を表示できる。
[root@linux ~]# fdisk -l -u hdd-2.img You must set cylinders. You can do this from the extra functions menu. Disk hdd-2.img: 0 MB, 0 bytes 125 heads, 62 sectors/track, 0 cylinders, total 0 sectors Units = sectors of 1 * 512 = 512 bytes Disk identifier: 0x911466d3 Device Boot Start End Blocks Id System hdd-2.img1 62 61999 30969 83 Linux hdd-2.img2 62000 123999 31000 83 Linux hdd-2.img3 124000 247999 62000 5 Extended hdd-2.img5 124062 185999 30969 83 Linux hdd-2.img6 186062 247999 30969 83 Linux [root@linux ~]#
ここで、1セクタ=512バイトなのでStartのセクタに512を掛けた値が各パーティションのHHDの先頭からのオフセット・バイト数となる。例えば、上の例のパーティション6(Startセクタ=185062)をマウントするには次のようにmountを実行する。(電卓で 186062 * 512 を計算してもいいが、以下の例では exprコマンドでの計算結果を直接mountのオプションに設定している。)
[root@linux ~]# mount -o loop,offset=`expr 186062 \* 512` hdd-2.img /mnt [root@linux ~]# ls /mnt lost+found [root@linux ~]#
fdiskを使えば、拡張パーティションも含めて表示できるので、通常はこれを使っていればいいが、パーティション・テーブルの構造を勉強するために、パーティションテーブルの情報をダンプする "partinfo" というコマンド作ってみた。これを使ってオフセットを調べることができる。(プログラムリストは「program list of "partinfo"」を参照。)例えば、パーティション1のオフセットを調べるには次のように実行する。
[root@linux ~]# partinfo -p 1 hdd.img Partition 1 Boot Flag = [80] Start Hd/Sc/Cy = [01/01/000] 1/1/0 Partition Type = [83] "Linux native partition" End Hd/Sc/Cy = [7c/3e/3f9] 124/62/1017 Start LBA = [0000003e] 62 sectors (31,744 bytes offset) Number of LBA = [0078621e] 7,889,438 sectors (4,039,392,256 bytes) [root@linux ~]#
これで、パーティション1の始まりはHDDの先頭から 31,744 バイトということが分かるので、mountコマンドのオプションoffsetで指定すればマウントできる。
なお、マウントできるパーティションはmountコマンドが認識できるファイルシステム形式あれば良く、FATやNTFS形式のパーティションもマウントして利用することができる。
■ kpartxコマンドを使う
fdiskやpartinfoのようなコマンドがあればオフセットを知るのは容易かと思うが、kpartxというコマンド使うことでより容易に(オフセットを計算せずに)任意のパーティションをマウントできる。kpartxはパーティション毎のブロック・デバイス・ファイルを /dev/mapper/の下に生成できる。丁度、ディスク /dev/sdaに対してパーティション1は /dev/sda1、パーティション2は /dev/sda2という風にパーティション毎に別々のデバイスファイルとして扱えるのと同様になる。
kpartxコマンドの使い方は以下の様な感じである。
[root@linux ~]# ls /dev/mapper/ ;: ←mapperの下は空(controlだけ) control [root@linux ~]# kpartx -v -a hdd-2.img ;: ←kpartxでデバイスを作成 add map loop1p1 : 0 61938 linear /dev/loop1 62 add map loop1p2 : 0 62000 linear /dev/loop1 62000 add map loop1p5 : 0 61938 linear /dev/loop1 124062 add map loop1p6 : 0 61938 linear /dev/loop1 186062 [root@linux ~]# ls /dev/mapper/ ;: ←mapperの下に作成されている control loop1p1 loop1p2 loop1p5 loop1p6 [root@linux ~]# ls /mnt ;: ←/mntの下が空なのを確認して [root@linux ~]# mount /dev/mapper/loop1p1 /mnt ;: ←1つのデバイスをマウントする [root@linux ~]# ls /mnt ;: ←/mntの下にファイルが現れる lost+found [root@linux ~]# umount /mnt ;: ←作業が終わったらumountして [root@linux ~]# kpartx -d hdd-2.img ;: ←kpartxでデバイスを削除 loop deleted : /dev/loop1 [root@linux ~]# ls /dev/mapper/ ;: ←mapperの下は再び空に control [root@linux ~]#
実用上はパーティション・テーブルからオフセット計算してマウントするよりは、kpartxコマンドを利用して個別のデバイス・ファイルをマウントする方が実際的だろう。ただ、気をつけないと、作業終了時にunmountするだけで、loopデバイスを開放するのを忘れてしまうので注意。