Raspberry PiでUSBに繋いだストレージ(USBメモリ・HDD・SSDなど)をマウントするちょっと素敵な方法
きっかけ
Raspberry Pi内のデータをUSBメモリにバックアップしたり、大きいデータを持つためにHDDをつないだりして、USBに複数のストレージデバイスが接続された時に、
- 各ストレージデバイスを一意に識別する方法
- 特に、全く同じ機種を複数接続したときに、それぞれを識別する方法
- 同じデバイスに対して、常に同じやり方でマウントできるようにする方法
- 特に、挿したUSBポートや、挿した順番とかに依存しない方法
を得たい。
Raspbianでは、/dev がUDEVによって管理されるので、その辺の設定ファイルを書く事で対処できる。
第1章 各デバイスのSERIAL IDが異なる場合
1. USBからストレージデバイスを全部外した状態で、Raspberry Piを起動。
ls /dev/sd*
で、「sdなんちゃら」(「なんちゃら」の所はアルファベット1文字になる)が出てこないのを確認。
2. 任意のストレージデバイスを1個だけ繋いでみる
ls /dev/sd*
すると、「sda」とか「sda1」とか出てくるはず。
場合によっては「sdb」とか「sdb1」とかかも。
ここでは「sda」「sda1」として話を進める。
3. マウントしてみて、どのデータを収めたデバイスなのかを確認する
※新品のデバイス2つを新たに接続したい場合とかのように、確認が不要な場合はこの項目は飛ばして下さい。
sudo mount /dev/sda1 /mnt
とか、
ls /mnt
とかやって、繋いだストレージデバイスがどれなのかを特定する。
確認したら、
sudo umount /dev/sda1
4. デバイスのIDを調べる
sudo udevadm info -q all -n /dev/sda
を実行すると、デバイスに関する情報がずらずらと表示される。
必要なのは、
E: ID_SERIAL=
の行。例えば、わたしの環境では、SanDiskのUSBメモリを繋いでいるので、
E: ID_SERIAL=SanDisk_Cruzer_Fit_00000000000000000000-0:0
みたいになる(数字の部分は適当に改変してます)。
「=」から右の部分をメモっておくとGOOD。
5. デバイスを外す
普通にUSB端子からズブッと抜いちゃいます。
7. UDEVのルールを書く
/etc/udev/rules.d 内に、このデバイスに6.で考えた名前を割り当てるためのルールファイルを書く。
ファイル名の先頭に出来るだけ大きな2桁の数字(99とか)を付ける。例えば、
99-usbmem_backup.rules
とか。
内容は以下を参考に。
SUBSYSTEM=="block", ENV{ID_BUS}=="usb", ENV{ID_SERIAL}=="SanDisk_Cruzer_Fit_00000000000000000000-0:0", SYMLINK+="usbmem_backup%n"
長いので行を分けているけれど、実際は一行で記述。
個別に変更する必要があるのは、
- 「ENV{ID_SERIAL}==」の右の部分。4.で調べたID_SERIALを使用。
- 「SYMLINK+=」の右の部分。6.で考えた名前を使用。
なおこのディレクトリはパーミッションの問題でrootしか書き込めないので、
- エディタをsudoで起動し、ファイルを作成する
- 他の場所にファイルを作成し、sudo cp でファイルをコピーする
のどちらかで対応。
8. 2~7を、接続したいデバイスそれぞれに対し実施する
9. 完了
特にudevを再起動する必要とかはなし。
デバイスを挿した時ごとに、/etc/udev/rules.d 内を実行する模様。
あとは /etc/fstab に書くなり、必要なときにmountするなり、ご自由に。
第2章 デバイスが同じSERIAL IDを持つ場合
そんな場合があるのかどうか確かめてはいないが、もしそうであった場合には、各デバイスを識別するには他の方法を使うしかない。
例えば、USBのどのポートに繋いだかという情報を元に設定するとか。
1. USBからストレージデバイスを全部外した状態で、Raspberry Piを起動。
第1章の1.と同じ。
3. マウントしてみて、どのデータを収めたデバイスなのかを確認する
第1章の3.と同じ。
4.デバイスの刺さっているUSBポート番号を調べる
第1章と同様に、コマンドラインで
sudo udevadm info -q all -n /dev/sda
を実行すると、デバイスに関する情報がずらずらと表示される。
今度は、必要なのは、
E: ID_PATH_TAG=
の行。例えば、わたしの環境では、SanDiskのUSBメモリを繋いでいるので、
E: ID_PATH_TAG=platform-bcm2708_usb-usb-0_1_2_1_0-scsi-0_0_0_0
とか、別のポートにつなぐと、
E: ID_PATH_TAG=platform-bcm2708_usb-usb-0_1_3_1_0-scsi-0_0_0_0
「=」から右の部分をメモっておくとGOOD。
5. デバイスを外す
第1章と同じ。
6. デバイスの固有の名前を考える。
第1章と同じ。
7. UDEVのルールを書く
/etc/udev/rules.d 内に、このデバイスに6.で考えた名前を割り当てるためのルールファイルを書く。
ファイル名の先頭に出来るだけ大きな2桁の数字(99とか)を付ける。例えば、
99-usbmem_backup.rules
とか。
内容は以下を参考に。
SUBSYSTEM=="block", ENV{ID_BUS}=="usb", ENV{ID_PATH_TAG}=="platform-bcm2708_usb-usb-0_1_2_1_0-scsi-0_0_0_0", SYMLINK+="usbmem_backup%n"
長いので行を分けているけれど、実際は一行で記述。
個別に変更する必要があるのは、
- 「ENV{ID_PATH_TAG}==」の右の部分。4.で調べたID_PATH_TAGを使用。
- 「SYMLINK+=」の右の部分。6.で考えた名前を使用。
なおこのディレクトリはパーミッションの問題でrootしか書き込めないので、
- エディタをsudoで起動し、ファイルを作成する
- 他の場所にファイルを作成し、sudo cp でファイルをコピーする
のどちらかで対応。
8. 2~7を、接続したいデバイスそれぞれに対し実施する
9. 完了
第1章と同じ。
ただし、USBのポート番号だけで判別している(何が挿さっているか見ていない)ので、実際に運用する場合には挿すUSBのポートを変えないように。
ちなみに、UDEVのルールにはワイルドカードが使えるので、
- USBのポート2か3に繋いだデバイスに指定の名前を付けたい
というような場合には、例えば
SUBSYSTEM=="block", ENV{ID_BUS}=="usb", ENV{ID_PATH_TAG}=="platform-bcm2708_usb-usb-0_1_[23]_1_0-scsi-0_0_0_0", SYMLINK+="usbmem_backup%n"
とかやると、USBのポート2か3に接続されたデバイスを、「/dev/usbmem_backup」等の名前にすることが可能。
さらに、
- USBの特定のポート(複数可)に接続された
- あるSERIAL IDを持ったデバイス
に対するルールも定義可能。
例えば、
SUBSYSTEM=="block", ENV{ID_BUS}=="usb", ENV{ID_PATH_TAG}=="platform-bcm2708_usb-usb-0_1_[23]_1_0-scsi-0_0_0_0", ENV{ID_SERIAL}=="SanDisk_Cruzer_Fit_00000000000000000000-0:0", SYMLINK+="usbmem_backup%n"
とか書いたら、USBのポート2か3に接続された、指定のSERIAL IDを持つデバイスを「usbmem_backup」等の名前にすることが可能。