LinuxでUSB外付けディスクを快適にマウントする

LinuxでUSB外付けディスクをつないでマウントしようとするとき、接続する順番や環境によって各デバイスが/devディレクトリのどこにマップされるのかが一意に定まりません。このため、頻繁に外付けディスクを使うことが前提となる環境において、マウントポイントを自動的に統一することができず非常に不便です。そこでこのエントリでは、外付けディスクのマウントの煩わしさを解決する方法を紹介いたします。

Debianをはじめとして、最近のLinuxディストリビューションで採用されているカーネルでは、接続されているディスクを、接続順や接続環境に依らずに一意に判別するため、画期的な手段を用意しています。 具体的には /dev/disk/ 以下にID,Label,Path,UUIDの4種類からデバイスマップを取得できるのです。

```
$ ls /dev/disk/
by-id  by-label  by-path  by-uuid
```

それぞれのディレクトリには各ディスクやパーティーションのデバイスファイルにシンボリックリンクが張られており、ディスクが持つ固有情報をキーとして利用し、マウントに活用することができます。

このエントリでは、利用できる4つのキーのうちUUIDを利用することによって、接続順に依らず自動的に同じ場所にマウントする環境を実装してみます。
UUIDは、Universally Unique Identifierの略語で、様々なデバイスを一意に識別するために利用されるものです。こう表現すると難しく聞こえますが、たいていの場合何も考えなくてもすでに割り振られているIDですから、このIDを有効活用してみましょう。

## 準備

用意するのは外付けUSBディスクとしてUSBメモリ(SanDisk cruser mini 128MB)と外付けHDD(1TB SATA-USB変換ケース入り)の2つ、接続するPCはDebian lennyをインストールした自作NAS(D945GCLF2 RAM:1GB HDD:1TB)です。
なお、Debianのランレベルは2で、Gnome環境やKDE環境の自動マウントは無効になっているものとします。 では、基本編と応用編に分け、実装方法を紹介していきます。

## 基本編

まず、同じデバイスを同じ場所にマウントをするには、以下の2つの作業を行います。

 1. 各デバイスのUUIDを調べる
 2. UUIDを利用してマウントする

では、順番に確認していきましょう。

### 各デバイスのUUIDを調べる

まず、各デバイスのUUIDを調べてみます。 まずUSBメモリから調べます。USBメモリをPCに接続し、直後に以下のコマンドを実行します。

```
$ dmesg | tail -n 22
[428873.472359] usb 5-5: new high speed USB device using ehci_hcd and address 3
[428873.614823] usb 5-5: configuration #1 chosen from 1 choice
[428873.614823] scsi3 : SCSI emulation for USB Mass Storage devices
[428873.621762] usb-storage: device found at 3
[428873.621762] usb-storage: waiting for device to settle before scanning
[428873.621762] usb 5-5: New USB device found, idVendor=0781, idProduct=5150
[428873.621762] usb 5-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[428873.621762] usb 5-5: Product: Cruzer Mini
[428873.621762] usb 5-5: Manufacturer: SanDisk Corporation
[428873.621762] usb 5-5: SerialNumber: SNDK4CC8443998600107
[428879.935348] usb-storage: device scan complete
[428879.935348] scsi 3:0:0:0: Direct-Access     SanDisk  Cruzer Mini      0.1  PQ: 0 ANSI: 2
[428879.943847] sd 3:0:0:0: [sdb] 250879 512-byte hardware sectors (128 MB)
[428879.943847] sd 3:0:0:0: [sdb] Write Protect is off
[428879.943847] sd 3:0:0:0: [sdb] Mode Sense: 03 00 00 00
[428879.943847] sd 3:0:0:0: [sdb] Assuming drive cache: write through
[428879.947843] sd 3:0:0:0: [sdb] 250879 512-byte hardware sectors (128 MB)
[428879.947843] sd 3:0:0:0: [sdb] Write Protect is off
[428879.947843] sd 3:0:0:0: [sdb] Mode Sense: 03 00 00 00
[428879.947843] sd 3:0:0:0: [sdb] Assuming drive cache: write through
[428879.947843]  sdb: sdb1 sdb2 < >
[428879.968840] sd 3:0:0:0: [sdb] Attached SCSI removable disk
```

すると、接続されたデバイスの情報が表示されます。今回のこの表示では、`[sdb]`という文字列から、`/dev/sdb`にマップされたことがわかります。また、このUSBメモリのパーティーション情報を得られ、`/dev/sdb1`, `/dev/sdb2`がそれらに対応しているということも下から2行目の情報で判断できます。
なお、2つのパーティーションが認識されていますが、製品によってパーティーション構成は異なるので、適宜読み替える必要があります。今回の製品は`sdb1`のみをデータ保存領域として利用しているものなので、`sdb1`をマウント対象とします。

では、この`/dev/sdb1`がマウントしたいパーティーションだということがわかったので、このUUIDを調べましょう。といっても特別な作業は必要ありません。 接続してから`/dev/disk/by-uuid/`のファイルリストを見てみます。

```
$ ls -al /dev/disk/by-uuid/ | grep sdb
lrwxrwxrwx 1 root root  10 2008-11-15 16:34 3B69-1AFD -> ../../sdb1
```

`3B69-1AFD`というシンボリックリンクが/dev/sdb1に向けて張られていることがわかります。
この`3B69-1AFD`という文字列が今回試すUSBメモリのUUIDです。
仮に、接続順などの関係でデバイスが異なる場所にマップされても、この`/dev/disk/by-uuid/3B69-1AFD`というシンボリックリンクが適宜リンク先を張り替えてくれるので、マウント時のデバイス名の代わりにこのシンボリックリンクを指定するようにすれば、デバイスのマップ名をいちいち調べ直さなくてもよいことになります。

ちなみに、UUIDのほか様々なパーティーション情報を取得するコマンドに`vol_id`というものがあります。

```
$ /lib/udev/vol_id /dev/sdb1
ID_FS_USAGE=filesystem
ID_FS_TYPE=vfat
ID_FS_VERSION=FAT16
ID_FS_UUID=3B69-1AFD
ID_FS_UUID_ENC=3B69-1AFD
ID_FS_LABEL=*****
ID_FS_LABEL_ENC=*****
ID_FS_LABEL_SAFE=*****
```
この結果からも`ID_FS_UUID`フィールドの値、つまり`3B69-1AFD`がUUIDであることを確認できました。
ほかにも、ファイルシステムがFAT16であることなど、マウント時に有用な情報が得られるので、こちらのコマンドも覚えておくと便利かもしれません。

### UUIDを利用してマウントする

UUIDもわかったところで、実際にマウントをしてみましょう。 まず、マウントポイントを作成します。(要root権限)

```
$ sudo mkdir /mnt/usbdisk1
```

作成したマウントポイントにUSBメモリをマウントします。
ファイルシステムは`vfat`を指定し、書き込み権限を一般ユーザにも与えるために`umask=000`を指定することにします。(要root権限)

```
$ sudo mount /dev/disk/by-uuid/3B69-1AFD /mnt/usbdisk1 -t vfat -o umask=000
```

エラーが出なければマウント成功です。
上記のmountコマンドをスクリプトか何かに保存しておけば、いちいちデバイス名を調べる必要がなくなるのです。(ちなみにmountコマンドの`-U` オプションでもUUIDを利用したマウントができますが、結果は同じです ) 
では、dfコマンドでマウント結果を見てみましょう。

```
$ df | grep sdb
/dev/sdb1               125216     99888     25328  80% /mnt/usbdisk1
```

問題なくマウントできました。 他のUSB外付けディスクのUUIDについても同様の方法で調べ、すべて把握しておけば、いくつどの順番でデバイスを接続したとしても、どこにマップしているかを調べる必要がないので、2回目以降のマウント作業はとても便利になるでしょう。

## 応用編

基本ができたら、autofsというツールを使ってさらに便利な環境を構築してみましょう。
autofsは、マウントオプションなどを事前に登録しておけば、マウントとアンマウントをファイルアクセス要求に応じて自動的に行うツールです。autofsの設定ファイルにUUIDを活用するのです。

### autofsの導入

Ubuntuをはじめとした最近のディストリビューションにはautofsのパッケージが用意されているので導入は非常に簡単です。(要root権限)

```
$ sudo apt-get install autofs  # Ubuntuの場合
```

### uuidをautofsに登録

インストールが完了したら2つの設定ファイルを書き換え、autofsにUSB外付けディスクのUUIDを登録します。(要root権限)

```
$ sudo vi /etc/auto.master   # マスターファイルに /misc ディレクトリへのマウントを行うよう設定
/misc   /etc/auto.misc  # この行のコメントアウト"#"を外す
```
USB外付けディスクのUUIDは`auto.misc`に登録していきます。(要root権限) 
なお、マウントオプションは適宜パーティーションに応じて変更する必要がありますので注意してください。

```
$ sudo vi /etc/auto.misc
cruzermini      -fstype=vfat,umask=000          :/dev/disk/by-uuid/3B69-1AFD # Cruzer mini
exthdd0         -fstype=ext3            :/dev/disk/by-uuid/a649dea8-d1fe-444a-83a4-ae44c40b1db9 # 1TB HDD SATA-USB外付けケース入り
```

ファイルの編集が終わったらautofsを再起動します。(要root権限)

```
$ sudo service autofs restart
```

設定が正しく反映されているか見てみます。

```
$ ls -al /misc/crusermini /misc/exthdd0
/misc/cruzermini:
total 47696
(省略)

/misc/exthdd0:
total 28
(省略)
```

UUIDを指定して自動マウントを行うことができました。
このようにしておけば、接続順を気にせずに固定のマウントポイントでUSB外付けディスクにアクセス可能です。

なお、autofsは一定時間のアクセスがない場合、自動的にデバイスをアンマウントしてくれますが、取り外すときには必ずdfコマンドでマウントされていないことを確認してから取り外すようにしましょう。
アンマウントされていない場合は、root権限でumountで手動アンマウントし、取り外せば問題ありません。

以上、UUIDを利用したUSB外付けディスクのマウント方法をご紹介しました。 もちろんUUID以外にもラベルやデバイスIDを使うことでも同様のことができます。

この方法は、Linuxでやっかいだった外付けディスクのマウントの煩わしさを鮮やかに解決してくれます。 是非、一度は試されることをお勧めします。