第555回ではデバイスの自動認識やデバイス名の設定など、システムの裏方として大活躍しているudevの基本とルールファイルの書き方について紹介しました。今回はルールを書く上で便利なツールであるudevadmを紹介します。
udevのデバッグ方法
udevはまずinitシステムからudevdが起動され、以降はudevdが諸々の処理を行います。よってudevの挙動をより細かく知るためには、udevdのログレベルを初期状態のinfoからdebugにあげて起動しておくと便利です。udevdのログレベルを変更するには4種類の方法が存在します。
- カーネルパラメーターから指定する
- /etc/udev/udev.confから設定する
- udevadmコマンドから設定する
- 環境変数
SYSTEMD_LOG_LEVEL
で設定する
このうち起動直後からdebugレベルにしたり、恒久的に設定したいなら、カーエネルパラメーターかudev.confを使うことになります。起動後に一時的にオン・オフするならudevadmコマンドが便利です。
カーネルパラメーターから指定する
比較的設定しやすいのがカーネルパラメーターに設定する方法です。次のようなパラメーターを設定します。
「rd.
」で始まっているパラメーターは、initramfs環境でのみ効きます。通常の環境と両方で有効化したいなら、前者だけでかまいません。
カーネルパラメーターは「/etc/default/grub
」「GRUB_CMDLINE_LINUX
」に設定します。具体的には次のような値になります。
エディタを使用しないなら次のコマンドを実行します。
エディタを使用するしないに関わらず、更新したら「update-grub
」を実行してください。変更したら再起動しましょう。
カーネルパラメーターに指定したパラメーターが表示されていることを確認しましょう。
ログを見るとudev関連のログが大量に出ています。たとえば次の内容から、ロードされているルールファイルがわかります。
デバッグログはかなりの量が出力されますし、起動時間も長くなってしまいます。必要がなくなったら元に戻しておきましょう。
/etc/udev/udev.confから設定する
もうひとつよく紹介されるのがudev.confに設定する方法です。特定のinitramfsでのみログレベルなどの設定を反映したい場合に使えますし、カーネルパラメーターと異なり、ログレベル以外も設定できます。
設定ファイルは「/etc/udev/udev.conf
」です。「#
」で始まる行はコメント行なので、次のように設定します。
さらにこの設定ファイルはudevが起動するinitramfsの中に含まれている必要があります。Ubuntuの場合、initramfsを更新したら最新のudev.confが含まれるようになっています。
ちなみに「/usr/share/initramfs-tools/scripts/init-top/udev
」はinitramfs内部のudevの起動スクリプトです。ログレベル以外の挙動を一時的に変えたいなら、こちらのファイルを直接編集してupdate-initramfsを実行しても良いでしょう。ただしこのファイルはudevパッケージのアップデートによって上書きされるので注意してください。
udevadmの使い方
「udevadm
」はudevに問い合わせ・操作を行うためのコマンドラインツールです[1]。たとえば認識済みのデバイスのudevイベント情報を表示してルールファイルを作る際の参考にしたり、イベントの内容をリアルタイム標準出力に出すことでホットプラグ時のイベントを確認できます。
udevのイベントを表示する「monitor」
いちばんわかりやすいのがudevのイベントを表示するmonitorサブコマンドでしょう。起動は「udevadm monitor
」を実行するだけです。終了はCtrl-Cを押してください。
上記はBluetoothドングルを接続した時のイベントです。実際はcgroupあたりのイベントも表示されますが、今回は間引いています。
KERNELで始まる行はカーネルから届いたueventです。udevはueventを受け取って、それを元にルールファイルを処理し、UDEVで始まる行を出力します。第555回の「ACTIONとGOTO変数」でも紹介しているように、「add」は「デバイスの追加」で「bind」は「ドライバーとデバイスが紐付けられた」状態となります。
「/devices/」で始まる文字列はイベントターゲットのデバイスパスです。これはそのまま「/sys」以下のディレクトリパスです。
たとえばこのPCはPCIバスのBus 00、Device 14、Function 0にUSBコントローラーがぶら下がっています。デバイスパスの「/pci0000:00/0000:00:14.0/usb3/」がそれに該当します。
さらに今回つないだUSBポートは、Bus 3、Port 1のUSBハブにつながっているようです。実際にlsusbしてみるとそれらしきデバイスが見えます。
このBluetoothドングルはインターフェースが2つあるようですね。
monitorサブシステムは「-p
」オプションを渡すと、プロパティも表示してくれます。プロパティは第555回で紹介したマッチングルールで利用できる値です。manページには記載がありませんが、過去との互換性のために「-p
」のエイリアスとして「--env
」オプションを使うことも可能です。
詳細な解説は省きますが、usbサブシステムの特定のポートにデバイスがaddされてから、udevにイベントが渡っていく様子がわかります。さらにudev自身がルールファイルを元に、さまざまなプロパティを追加していることもわかります。
USBなどのホットプラグなデバイスに対してルールファイルを作成する際は、この出力結果が参考になるでしょう。
デバイスのイベント情報を表示する「info」
認識済みのデバイスの情報(プロパティ)を表示したい場合は、infoサブコマンドを使います。表示したいデバイスのデバイスファイル名を「-n
」オプションに指定して実行します。
USBデバイスは「/dev/bus/usb/バス番号/デバイス番号
」のファイルが作られるのでこれを指定していますが、ストレージデバイスなら「/dev/sda1
」なども指定可能です。
さてinfoサブコマンドで表示されるデータには次のようなヘッダーが付けられています。
- P:デバイスパス
- N:デバイス名
- L:リンクプライオリティ[2]
- S:シンボリックリンク
- E:プロパティ
デバイスファイルが作られない場合、sysfs上のデバイスパスを「-p
」オプションに指定します。
得られる結果はデバイス名を指定したときと、原則同じです。
特定の情報だけを取得したい場合は「-q
」オプションでフィルタリングできます。たとえばデバイスパスを取得したければ次のように「path」を指定してください。
他にもデバイス名(name)、シンボリックリンク(symlink)、プロパティ(property)、すべて(all)を指定できます。
「-a
」オプションを付けると、親デバイスまでさかのぼって状態を表示してくれます。
イベントを発生させる「trigger」
triggerサブコマンドは、任意のイベントをカーネルから発生させられます。もし引数なしに実行した場合は、すべての認識済デバイスにchangeアクションのイベントを送ります。アクションの種類は第555回の「ACTIONとGOTO変数」を参照してください。
実際には事前に別のウィンドウで「udevadm monitor」を実行しておくと、状況がわかりやすいでしょう。
ひたすらchangeイベントが届いていますね。
「-c
」オプションで任意のアクションを指定できますし、末尾にデバイス名やデバイスパスを指定すれば、イベントを送る対象を制限できます。さらに「-v
」オプションを付けておくと、イベントを送る対象のデバイスが表示されます。
他にも属性やプロパティ、サブシステムなどでマッチングしてイベントを送る対象を制限できます。詳細はudevのmanページを参照してください。
単に特定のデバイス向けのルールファイルをテストしたいだけなら、testサブコマンドも使えます。
testサブコマンドはデバイスパスしか渡せないので、上記のようにデバイス名からの変換が必要です。
udevデーモンを操作する「control」
controlサブコマンドはudevデーモンそのものを操作するサブコマンドです。あまり使うことはありませんが、ログレベルを一時的に変更できる「-l
」やルールをリロードできる「-R
」、イベントの処理を一時的に停止・再開する「-s
」と「-S
」あたりは、覚えておくとデバッグ時に便利かもしれません。
udevのビルトインコマンドを実行する「test-builtin」
第555回の「ENVとRUN変数」でも紹介したように、ルールファイルの中でudevのビルトインコマンドを実行することがあります。このビルトインコマンドをシェルから実行できるのがtest-builtinサブコマンドです。次のようなビルトインコマンドをサポートしています。
blkid
:UUIDなどを取得する
btrfs
:btrfs関連の情報取得
hwdb
:hwdbからデータを取得
input_id
:入力デバイス関連の情報を取得
keyboard
:キーマッピングなどをスキャン
kmod
:カーネルモジュールのロード
net_id
:ネットワークデバイスの情報取得
net_setup_link
:ネットワークのリンク設定
path_id
:デバイスパスの元になる情報の取得
usb_id
:USB関連の情報を取得
uaccess
:アクセスコントロール関連の情報取得
ホットプラグ関連だと、usb_id
によるUSBデバイス情報がルールファイル作成時の参考になるでしょう。
ルールファイルの中でどのようなプロパティがセットされるか確認したいときに便利です。