下記の記事で保留にしていたudevの具体的な設定方法がわかりましたので,まとめておきます。

USBメモリでRAIDを構築する方法
USBメモリでRAIDを構築する方法《続編》

何が問題なのか


PCを再起動したり,USBメモリを挿し直したりすると,/dev/sdbが/dev/sdcや/dev/sddなどの他のデバイス名に置き換わってしまうことがあります。

今回のRAID構築に限らず,/etc/fstabを使った自動マウントの設定の際など,USBメモリのデバイス名を使う場面は結構あるのではないでしょうか?

最近のLinuxでは,udevというプログラムで自動的にデバイスを認識しています。Ubuntuで多くのハードウェアを設定なしに使えるのも,このudevのおかげなわけですが,今回はそれが裏目に出たということです。

このudevの設定を利用して,デバイス名を固定してみましょう。

/dev/sdbや/dev/sdcなどを直接固定するのは難しいようですので,/dev/sdxのxがどのように設定されても,特定のUSBメモリが常に/dev/usbhdaなどの新たな固定されたデバイス名になるようにするという方針で設定します。

STEP1.udevの設定ファイル


udevの設定(udevのルール)は,/etc/udev/rules.dというディレクトリの中にあるファイル群で指定されています。

これらのファイルを直接編集するのは危険なので,独自のルールを設定する場合は,新たに「96-local.rules」などの名前でファイルを作成します。ここで,それぞれのファイルの先頭の数字は,優先順位を表します。

udev-095-udev-late.rules」という数字95のファイルが最後にありましたので,他に影響が及ばないように,数字を96としました。

STEP2.USBメモリの固有情報を表示する


udevを設定するためには,USBメモリの固有情報を確かめておく必要があります。まず,次の手順でUSBメモリの現在のデバイス名を確認します。

USBメモリをUSBポートに挿入する前に,

$ cat /proc/partitions

を実行。USBメモリをUSBポートに挿入して,再び,

$ cat /proc/partitions

を実行。両者を見比べて,追加されたsdb,sdcなどが,そのUSBメモリのデバイス名です。追加されたものが「sdb」であれば,正確には/dev/sdbとなります。

デバイス名がわかったら,次のコマンドを実行します。/dev/sdbの部分は,確認したデバイス名に適宜置き換えて下さい。

$ udevinfo -a -p $(udevinfo -q path -n /dev/sdb)

udev-1KERNELS=="5-4.2"(数字は環境によって異なります)で始まるブロックに注目します。必要なのは,
ATTRS{serial}=="英数字"の部分。


なお,上の例ではUSBハブを利用しています。直接USBポートに挿した場合,ATTRS{serial}=="英数字"の部分は,小数点のないKERNELS=="5-4"で始まるブロックの中にあります。


STEP3.udevの設定ファイルを作成する


それでは,STEP2で確認した情報をもとにして,設定ファイルを書きましょう。次のコマンドで,エディタを開き,下に示したコードを記述するだけです。loval.rulesの先頭の数字は環境により異なります。/etc/udev/rules.d/の中を確認して,最大の数字より大きな数字にしておくといいでしょう。なお,USBハブを使うか使わないかで,微妙に異なります。

$ sudo gedit /etc/udev/rules.d/96-local.rules

【USBハブを介する間接接続の場合】
KERNEL=="sd*", SUBSYSTEM=="block", ATTR{removable}=="1", KERNELS=="[0-9]-[0-9].[0-9]", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{serial}=="VVN1xxxx", SYMLINK+="usbhda%n"
※ 赤字の部分に,STEP2で確認した英数字を記述します。

【USBハブを介さない直接接続の場合】
KERNEL=="sd*", SUBSYSTEM=="block", ATTR{removable}=="1", KERNELS=="[0-9]-[0-9]", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{serial}=="VVN1xxxx", SYMLINK+="usbhda%n"
※ 赤字の部分がハブを使うときとの相違点です。

【実際の例】
今回は,3つのUSBメモリを使いましたので,実例を挙げておきます。シリアルの英数字だけ一部伏せ字にしてありますが。

# "JetFlash Mass Storage Device 1"
KERNEL=="sd*", SUBSYSTEM=="block", ATTR{removable}=="1", KERNELS=="[0-9]-[0-9].[0-9]", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{serial}=="D15Ixxxx", SYMLINK+="usbhda%n"

# "JetFlash Mass Storage Device 2"
KERNEL=="sd*", SUBSYSTEM=="block", ATTR{removable}=="1", KERNELS=="[0-9]-[0-9].[0-9]", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{serial}=="WJXCxxxx", SYMLINK+="usbhdb%n"

# "JetFlash Mass Storage Device 3"
KERNEL=="sd*", SUBSYSTEM=="block", ATTR{removable}=="1", KERNELS=="[0-9]-[0-9].[0-9]", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{serial}=="VVN1xxxx", SYMLINK+="usbhdc%n"

これで,3つのUSBメモリは,/dev/usbhda,/dev/usbhdb,/dev/usbhdcという名前に固定されます。

STEP4.デバイス名が固定されていることの確認


以上で,固定された/dev/usbhdaなどの名称を用いて,fdiskなども実行できるようになるはずです。ここで,USBメモリを一度挿し直して,実際にうまくいっているかどうか確認してみましょう。

$ ls -la /dev/usbhd*

上記のコマンドを実行し,USBメモリを挿し直して,再度実行してみます(デバイスファイルのリンク先を確認しているだけです)。

udev-usb/dev/sdcと/dev/sddが入れ替わっています。

USBメモリを挿し直したことにより,/dev/sdcと/dev/sddが入れ替わっていますが,/dev/usbhdbと/dev/usbhdc自体は,元と同じUSBメモリのデバイス名になっているというわけです。

udevについては奥が深そうなので,今後もいろいろ勉強したいと思います。