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デバイスを開放するのを忘れてしまうので注意。