「Udev」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(→‎参照: 同期)
21行目: 21行目:
 
== udev ルールについて ==
 
== udev ルールについて ==
   
管理者が書いた ''udev'' ルールは {{ic|/etc/udev/rules.d/}} にり、そのファイル名は ''.rules'' で終わらなければなりません。様々なパッケージに同梱されている ''udev'' ルールは {{ic|/usr/lib/udev/rules.d/}} に格納されています。もし {{ic|/usr/lib}} と {{ic|/etc}} に同じ名前のファイルがあった場合、 {{ic|/etc}} にあるファイルが優先されます。
+
管理者が書いた ''udev'' ルールは {{ic|/etc/udev/rules.d/}} 配置することになっており、そのファイル名は ''.rules'' で終わらなければなりません。様々なパッケージに同梱されている ''udev'' ルールは {{ic|/usr/lib/udev/rules.d/}} に格納されています。もし {{ic|/usr/lib}} と {{ic|/etc}} に同じ名前のファイルがあった場合、{{ic|/etc}} にあるファイルが優先されます。
   
udev'' ルールについて学ぶには、{{man|7|udev}} マニュアルを参照してください。また、[http://www.reactivated.net/writing_udev_rules.html Writing udev rules] も参照してください。またいくつかの的な例がガイドの中で提供されています。[http://www.reactivated.net/writing_udev_rules.html#example-printer udev ルールの書き方 - ] も見てださい。
+
''udev'' ルールについて学ぶには、{{man|7|udev}} マニュアルを参照してください。また、[http://www.reactivated.net/writing_udev_rules.html Writing udev rules] も参照してください。このガイドには、実的な例 ([http://www.reactivated.net/writing_udev_rules.html#example-printer Writing udev rules - Examples]) がいつか挙げられてます
   
 
=== udev ルールの例 ===
 
=== udev ルールの例 ===
   
  +
以下は、ウェブカメラが接続された時に {{ic|/dev/video-cam}} シンボリックリンクを作成するルールの例です。
{{Warning|リムーバブルドライブをマウントするのに、udev ルールから {{ic|mount}} を呼ばないで下さい。FUSE ファイルシステムの場合、{{ic|Transport endpoint not connected}} エラーが起こります。代わりに自動マウントを適切に処理する [[udisks]] を使って下さい。}}
 
   
  +
ここで、カメラは既に接続されていて、{{ic|/dev/video2}} というデバイス名でロードされているとします。そして、以下の udev ルールを書く理由は、次回のブート時にデバイスファイルが別の名前 (例えば {{ic|/dev/video0}} など) になってしまうかもしれないからです (なので、{{ic|/dev/video-cam}} という固定のファイル名で参照できるようにしようというのが目的です)。
* udev ルールの書き方を学ぶには [http://www.reactivated.net/writing_udev_rules.html udev ルールの書き方] ([http://mux03.panda64.net/docs/udevrules_ja.html 日本語訳]) を見て下さい。
 
* udev ルールのサンプルを見るには [https://soosck.wordpress.com/2011/01/19/improved-udev-rule-arch-linux/ Improved Udev Rule For Arch Linux] を見て下さい。
 
   
  +
{{hc|1=$ udevadm info --attribute-walk --path=$(udevadm info --query=path --name=/dev/video2)|2=
以下はウェブカメラが接続されたときにシンボリックリンク {{ic|/dev/video-cam1}} を作るルールの例です。まず、カメラが接続されたときデバイス {{ic|/dev/video2}} にロードされていることを見つけたとします。このルールを書く理由は次のブート時にデバイスが {{ic|/dev/video0}} など他の名前で表示される可能性があるからです。
 
  +
Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices.
  +
It prints for every device found, all possible attributes in the udev rules key format.
  +
A rule to match, can be composed by the attributes of the device and the attributes from one single parent device.
   
  +
looking at device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0/video4linux/video2':
{{hc|# udevadm info -a -p $(udevadm info -q path -n /dev/video2)|<nowiki>
 
  +
KERNEL=="video2"
Udevadm info starts with the device specified by the devpath and then
 
  +
SUBSYSTEM=="video4linux"
walks up the chain of parent devices. It prints for every device
 
  +
...
found, all possible attributes in the udev rules key format.
 
  +
looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0':
A rule to match, can be composed by the attributes of the device
 
  +
KERNELS=="3-2:1.0"
and the attributes from one single parent device.
 
  +
SUBSYSTEMS=="usb"
  +
...
  +
looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2':
  +
KERNELS=="3-2"
  +
SUBSYSTEMS=="usb"
  +
ATTRS{idVendor}=="05a9"
  +
ATTRS{manufacturer}=="OmniVision Technologies, Inc."
  +
ATTRS{removable}=="unknown"
  +
ATTRS{idProduct}=="4519"
  +
ATTRS{bDeviceClass}=="00"
  +
ATTRS{product}=="USB Camera"
  +
...
  +
}}
   
  +
対象のウェブカメラを識別するために、''video4linux'' デバイスからは {{ic|1=KERNEL=="video2"}} と {{ic|1=SUBSYSTEM=="video4linux"}} という条件式が使用されています。それより 2 階層上を見ると、USB 親デバイス {{ic|1=SUBSYSTEMS=="usb"}} からはベンダー ID {{ic|1=ATTRS{idVendor}=="05a9"}} とプロダクト ID {{ic|1=ATTRS{idProduct}=="4519"}} を使ってウェブカメラをマッチさせています。
looking at device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0/video4linux/video2':
 
KERNEL=="video2"
 
SUBSYSTEM=="video4linux"
 
...
 
looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0':
 
KERNELS=="3-2:1.0"
 
SUBSYSTEMS=="usb"
 
...
 
looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2':
 
KERNELS=="3-2"
 
SUBSYSTEMS=="usb"
 
...
 
ATTRS{idVendor}=="05a9"
 
...
 
ATTRS{manufacturer}=="OmniVision Technologies, Inc."
 
ATTRS{removable}=="unknown"
 
ATTRS{idProduct}=="4519"
 
ATTRS{bDeviceClass}=="00"
 
ATTRS{product}=="USB Camera"
 
...
 
</nowiki>}}
 
   
  +
以上から、以下のようにこのデバイスにマッチするルールを作成することができます:
video4linux デバイスから {{ic|<nowiki>KERNEL=="video2"</nowiki>}} と {{ic|<nowiki>SUBSYSTEM=="video4linux"</nowiki>}} を使います、そして usb parent {{ic|<nowiki>SUBSYSTEMS=="usb"</nowiki>}}, {{ic|<nowiki>ATTRS{idVendor}=="05a9"</nowiki>}}, {{ic|<nowiki>ATTRS{idProduct}=="4519"</nowiki>}} から製造者・製品 ID を使ってウェブカメラをマッチさせます。
 
   
{{hc|/etc/udev/rules.d/83-webcam.rules|<nowiki>
+
{{hc|/etc/udev/rules.d/83-webcam.rules|2=
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", \
+
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam"}}
ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1"
 
</nowiki>}}
 
   
上の例{{ic|<nowiki>SYMLINK+="video-cam1"</nowiki>}} を使ってシンボリックリンクを作成していますが {{ic|<nowiki>OWNER="john"</nowiki>}} {{ic|<nowiki>GROUP="video"</nowiki>}} を使ってユーザーやグループを設定したり {{ic|<nowiki>MODE="0660"</nowiki>}} を使ってパーミッション設定することも簡単にできます。
+
ここ{{ic|1=SYMLINK+="video-cam"}} を使ってシンボリックリンクを作成していますが{{ic|1=OWNER="john"}} でデバイスの所有者を、{{ic|1=GROUP="video"}} でデバイスの所有グループを設定することもできます{{ic|1=MODE="0660"}} パーミッション設定できます。
   
ただし、デバイスが取り除かれた時に何かをするルールを書く時は、デバイスの属性にアクセス出来ないことに注意してください。この場合、プリセットのデバイス環境変数を使う必要があります。これらの環境変数を監視するには、デバイスを抜い時に次のコマンドを実行してください:
+
デバイスが取り除かれた時に何かを行ルールを記述したい場合は、デバイスの属性にアクセスできないことに注意してください (とっくにデバイスは取り除かれているからです)。この場合、事前に定義されたデバイスの[[環境変数]]を使う必要があります。ような環境変数を監視するには、デバイスが取り除かれ状態で以下のコマンドを実行してください:
# udevadm monitor --environment --udev
 
   
  +
$ udevadm monitor --property --udev
このコマンドの出力の中に、{{ic|ID_VENDOR_ID}} や {{ic|ID_MODEL_ID}} などの、前に使っていた属性 "idVendor" と "idProduct" に一致する値があるはずです。デバイスの環境変数を使うルールは以下のようになります:
 
{{hc|/etc/udev/rules.d/83-webcam-removed.rules|<nowiki>
 
ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="05a9", ENV{ID_MODEL_ID}=="4519", RUN+="/path/to/your/script"
 
</nowiki>}}
 
   
  +
このコマンドでは、{{ic|ID_VENDOR_ID}} と {{ic|ID_MODEL_ID}} というような値のペアが出力されます。これらは、上記の属性 {{ic|idVendor}} と {{ic|idProduct}} に対応します。デバイスの属性の代わりにデバイスの環境変数を使うルールは以下のようになります:
=== デバイスの属性を一覧する ===
 
   
  +
{{hc|/etc/udev/rules.d/83-webcam-removed.rules|2=ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="05a9", ENV{ID_MODEL_ID}=="4519", RUN+="''/path/to/your/script''"}}
ルールを書くために使用できるデバイスのすべての属性のリストを取得するには、次のコマンドを実行します。
 
  +
  +
=== デバイスの属性を一覧表示する ===
  +
  +
ルールを書く際に使用できるデバイスの属性のリストを全て一覧表示するには、以下のコマンドを実行してください:
   
 
$ udevadm info --attribute-walk --name=''device_name''
 
$ udevadm info --attribute-walk --name=''device_name''
   
{{ic|''device_name''}} {{ic|/dev/sda}}{{ic|/dev/ttyUSB0}} など、システムに存在するデバイスに置き換えてください。
+
{{ic|''device_name''}} の部分は、システムに存在しているデバイス ({{ic|/dev/sda}}{{ic|/dev/ttyUSB0}} など) に置き換えてください。
   
デバイス名が分からない場合は、特定のシステムパスの全属性をリストアップすることもできます
+
デバイス名が分からない場合は、特定のシステムパスの全属性をリストアップすることもできます:
   
 
$ udevadm info --attribute-walk --path=/sys/class/backlight/acpi_video0
 
$ udevadm info --attribute-walk --path=/sys/class/backlight/acpi_video0
   
デバイスを絞り込むには、クラスを把握し、実行する。
+
デバイスを絞り込むには、まずデバイスのクラスを調べて以下のコマンドを実行してください:
   
 
$ ls /dev/''class''/by-id
 
$ ls /dev/''class''/by-id
   
シンボリックリンクをそのまま、あるいはそれがし示のを {{ic|--name}} の入力として使用することできます。例えば
+
{{ic|--name}} 引数には、単にデバイスのシンボリックリンクを使うこともできすしシンボリックリンクの指す実際アイルを使ことできます。例えば:
   
 
$ udevadm info --attribute-walk --name=/dev/input/by-id/usb-foostan_Corne-event-kbd
 
$ udevadm info --attribute-walk --name=/dev/input/by-id/usb-foostan_Corne-event-kbd
   
下位デバイスを持たない裸のUSBデバイスのパスを取得するには、 USB デバイスのフルパスを使用する必要があります。モニターモードを起動し、 USB デバイスを接続することで取得できます
+
下位デバイスを持たない裸のUSBデバイスのパスを取得するには、 USB デバイスのフルパスを使用する必要があります。''udevadm'' のモニターモードを開始し、対象の USB デバイスを接続すれば、デバイスへのパスを得ることできます:
   
 
{{hc|1=$ udevadm monitor|2=
 
{{hc|1=$ udevadm monitor|2=
109行目: 102行目:
 
}}
 
}}
   
一番深いパスを選択すれば {{ic|''--attribute-walk''}} はとにかく親の属性を全て表示します
+
一番深いパスを選択、{{ic|''--attribute-walk''}} を使えば、デバイス属性を出力することができます:
  +
  +
$ udevadm info --attribute-walk --path=''/devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:05.0/0000:05:00.0/usb1/1-3/1-3:1.0''
   
 
=== ロードする前にルールをテストする ===
 
=== ロードする前にルールをテストする ===
  +
# udevadm test $(udevadm info -q path -n [device name]) 2>&1
 
  +
# udevadm test $(udevadm info --query=path --name=''device_name'') 2>&1
このコマンドは新しいルールの全てのアクションを実行はしませんが、既存のデバイスのシンボリックリンクのルールは処理します。ロードできないときに役に立つかもしれません。また、テストしたい udev ルールのデバイスのパスを直接指定することも可能です:
 
  +
  +
このコマンドは、ルールの全てのアクションを実行しませんが、既存のデバイスに対するシンボリックリンクのルールは処理します。ルールをロードできない場合に役立つかもしれません。また、テストしたい ''udev'' ルールのデバイスへのパスを直接指定することも可能です:
  +
 
# udevadm test /sys/class/backlight/acpi_video0/
 
# udevadm test /sys/class/backlight/acpi_video0/
   
 
=== 新しいルールをロードする ===
 
=== 新しいルールをロードする ===
   
''udev'' はルールファイルの変更を自動的に検出するので、''udev'' を再起動するこなく、変更は直ちに有効になります。しかし、既に存在するデバイスに対しては、ルール自動的に再トリガされません。USB デバイスのようなホットプラグ可能なデバイスは、おそらく新しい規則を有効にするために再接続するか、少なくとも ohci-hcd と ehci-hcd カーネルモジュールアンロードして再ロードし、それによっすべての USB ドライバを再ロードしなければならないでしょう
+
''udev'' はルールファイルの変更を自動的に検出するので、''udev'' を再起動せず変更は即座に有効になります。しかし、既に存在するデバイスに対しては、ルール自動的に再トリガされません。USB デバイスなどのホットプラグ可能なデバイスは、新しいルールを有効にするために再接続するか、少なくともカーネルモジュール ohci-hcd と ehci-hcd を再ロードしてての USB ドライバを再読み込みする必要があります
   
ルールが自動的にリロードされない場合
+
ルールが自動的に再読み込みされない場合は、以下を実行してください:
   
 
# udevadm control --reload
 
# udevadm control --reload
   
手動で ''udev'' にルールを強制的に起動させるには
+
手動でルールを強制的にトリガーするには:
   
 
# udevadm trigger
 
# udevadm trigger

2023年12月14日 (木) 16:38時点における版

関連記事

udev は、オペレーティングシステムの管理者がユーザー空間のイベントハンドラを登録できるようにする、ユーザー空間のシステムです。udev のデーモンによって捕捉されたイベントは主に、周辺機器関連の物理イベントに応答して (Linux) カーネルによって生成されたものです。そのため、udev の主な使用目的は、(カーネルモジュールやデバイスファームウェアのロードなど) カーネルに制御が戻るようなアクションを含む、周辺機器の検出やホットプラグです。また、周辺機器の検出においては、デバイス (ファイル) のパーミッションを調整して非 root ユーザーや非 root グループからアクセス可能にするなども行われます。

udev は、devfsdhotplug の後継として、/dev ディレクトリ内のデバイスノードの追加、シンボリックリンクの作成、名称変更などの管理も行います。udevhotplughwdetect の両方の機能を置き換えます。

udev は、別々のイベントを同時に (並列に) 処理します。それにより、古いシステムよりも高いパフォーマンスが得られる可能性があります。しかし、カーネルモジュールのロード順がブート毎に同じであることが保証されないなどの理由により、この機構はシステムの管理を複雑化させてしまう可能性もはらんでいます。マシンに複数のブロックデバイスが搭載されている場合、再起動するとデバイスノードの名称が変化してしまう場合があります。例えば、マシンに 2 つのハードドライブが存在する場合、/dev/sda は次回の起動時に /dev/sdb となってしまうかもしれません。これに関する詳細は、下記を見てください。

目次

インストール

udevsystemd の一部なので、デフォルトでインストールされます。詳細は systemd-udevd.service(8) を見てください。

udev ルールについて

管理者が書いた udev ルールは /etc/udev/rules.d/ 内に配置することになっており、そのファイル名は .rules で終わらなければなりません。様々なパッケージに同梱されている udev ルールは /usr/lib/udev/rules.d/ に格納されています。もし /usr/lib/etc に同じ名前のファイルがあった場合、/etc にあるファイルが優先されます。

udev ルールについて学ぶには、udev(7) マニュアルを参照してください。また、Writing udev rules も参照してください。このガイドには、実践的な例 (Writing udev rules - Examples) がいくつか挙げられています。

udev ルールの例

以下は、ウェブカメラが接続された時に /dev/video-cam シンボリックリンクを作成するルールの例です。

ここで、カメラは既に接続されていて、/dev/video2 というデバイス名でロードされているとします。そして、以下の udev ルールを書く理由は、次回のブート時にデバイスファイルが別の名前 (例えば /dev/video0 など) になってしまうかもしれないからです (なので、/dev/video-cam という固定のファイル名で参照できるようにしようというのが目的です)。

$ udevadm info --attribute-walk --path=$(udevadm info --query=path --name=/dev/video2)
Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices.
It prints for every device found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device and the attributes from one single parent device.

looking at device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0/video4linux/video2':
  KERNEL=="video2"
  SUBSYSTEM=="video4linux"
   ...
looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0':
  KERNELS=="3-2:1.0"
  SUBSYSTEMS=="usb"
  ...
looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2':
  KERNELS=="3-2"
  SUBSYSTEMS=="usb"
  ATTRS{idVendor}=="05a9"
  ATTRS{manufacturer}=="OmniVision Technologies, Inc."
  ATTRS{removable}=="unknown"
  ATTRS{idProduct}=="4519"
  ATTRS{bDeviceClass}=="00"
  ATTRS{product}=="USB Camera"
  ...

対象のウェブカメラを識別するために、video4linux デバイスからは KERNEL=="video2"SUBSYSTEM=="video4linux" という条件式が使用されています。それより 2 階層上を見ると、USB 親デバイス SUBSYSTEMS=="usb" からはベンダー ID ATTRS{idVendor}=="05a9" とプロダクト ID ATTRS{idProduct}=="4519" を使ってウェブカメラをマッチさせています。

以上から、以下のようにこのデバイスにマッチするルールを作成することができます:

/etc/udev/rules.d/83-webcam.rules
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam"

ここで、SYMLINK+="video-cam" を使ってシンボリックリンクを作成していますが、OWNER="john" でデバイスの所有者を、GROUP="video" でデバイスの所有グループを設定することもできますし、MODE="0660" でパーミッションも設定できます。

デバイスが取り除かれた時に何かを行うルールを記述したい場合は、デバイスの属性にはアクセスできないことに注意してください (とっくにデバイスは取り除かれているからです)。この場合、事前に定義されたデバイスの環境変数を使う必要があります。そのような環境変数を監視するには、デバイスが取り除かれた状態で以下のコマンドを実行してください:

$ udevadm monitor --property --udev

このコマンドでは、ID_VENDOR_IDID_MODEL_ID というような値のペアが出力されます。これらは、上記の属性 idVendoridProduct に対応します。デバイスの属性の代わりにデバイスの環境変数を使うルールは以下のようになります:

/etc/udev/rules.d/83-webcam-removed.rules
ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="05a9", ENV{ID_MODEL_ID}=="4519", RUN+="/path/to/your/script"

デバイスの属性を一覧表示する

ルールを書く際に使用できるデバイスの属性のリストを全て一覧表示するには、以下のコマンドを実行してください:

$ udevadm info --attribute-walk --name=device_name

device_name の部分は、システムに存在しているデバイス (/dev/sda/dev/ttyUSB0 など) に置き換えてください。

デバイス名が分からない場合は、特定のシステムパスの全属性をリストアップすることもできます:

$ udevadm info --attribute-walk --path=/sys/class/backlight/acpi_video0

デバイスを絞り込むには、まずデバイスのクラスを調べて、以下のコマンドを実行してください:

$ ls /dev/class/by-id

--name 引数には、単にデバイスのシンボリックリンクを使うこともできますし、シンボリックリンクの指す実際のアイルを使うこともできます。例えば:

$ udevadm info --attribute-walk --name=/dev/input/by-id/usb-foostan_Corne-event-kbd

下位デバイスを持たない裸のUSBデバイスのパスを取得するには、 USB デバイスのフルパスを使用する必要があります。udevadm のモニターモードを開始し、対象の USB デバイスを接続すれば、デバイスへのパスを得ることができます:

$ udevadm monitor
...
KERNEL[26652.638931] add      /devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:05.0/0000:05:00.0/usb1/1-3 (usb)
KERNEL[26652.639153] add      /devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:05.0/0000:05:00.0/usb1/1-3/1-3:1.0 (usb)
...

一番深いパスを選択し、--attribute-walk を使えば、親デバイスの全属性を出力することができます:

$ udevadm info --attribute-walk --path=/devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:05.0/0000:05:00.0/usb1/1-3/1-3:1.0

ロードする前にルールをテストする

# udevadm test $(udevadm info --query=path --name=device_name) 2>&1

このコマンドは、ルールの全てのアクションを実行しませんが、既存のデバイスに対するシンボリックリンクのルールは処理します。ルールをロードできない場合に役立つかもしれません。また、テストしたい udev ルールのデバイスへのパスを直接指定することも可能です:

# udevadm test /sys/class/backlight/acpi_video0/

新しいルールをロードする

udev はルールファイルの変更を自動的に検出するので、udev を再起動せずとも変更は即座に有効になります。しかし、既に存在するデバイスに対しては、ルールが自動的に再トリガーされません。USB デバイスなどのホットプラグ可能なデバイスは、新しいルールを有効にするために再接続するか、少なくともカーネルモジュール ohci-hcd と ehci-hcd を再ロードして全ての USB ドライバを再読み込みする必要があります。

ルールが自動的に再読み込みされない場合は、以下を実行してください:

# udevadm control --reload

手動でルールを強制的にトリガーするには:

# udevadm trigger

Udisks

Udisks を見て下さい。

ヒントとテクニック

ルールの中でのドライブのマウント

リムーバブルドライブをマウントするには、udev ルールから mount を呼び出さないようにしてください。これは2つの理由でお勧めできません。(1) systemd はデフォルトで systemd-udevd.service を個別の マウント名前空間 (namespaces(7) を参照) で実行します、これはマウントがシステムの残りの部分から見えないことを意味します。(2) これを解決するためにサービスパラメータを変更しても (PrivateMountsMountFlags 行をコメントアウトする)、Udev から起動したプロセスが数秒後に終了してしまうという別の問題があります。NTFS-3G のような FUSE ファイルシステムの場合、mount はファイルシステム内部を処理するためにユーザースペースプロセスを起動します。これが殺されると、ファイルシステムにアクセスしようとすると Transport endpoint not connected エラーが発生することになります。

機能するオプションもあります。

  • systemd サービスは、(FUSE のような) 長時間実行するプロセスをいくつでも開始できるスクリプトを呼び出すことができます。systemd サービスは、(FUSE のような) 長時間稼働するプロセスをいくつでも起動できるスクリプトを起動できます。/media の下で USB ディスクを自動的にマウントする簡潔な例は udev-media-automount です。これは高速で信頼できることが確認されています。同じアイデアのバリエーションが このブログの記事 で説明されています。
  • Udev のルールで mount の代わりに systemd-mount を使ってください。これは systemd の開発者が推奨しています。 例えば、この Udev ルールは USB ディスクを "/media" 以下にマウントするものです。
ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode /media"
ただし、この記事を書いている時点では、信頼性が低いことが判明しています。
  • udisksudiskie のようなパッケージを使用してください。これらは非常に強力ですが、セットアップが困難です。また、これらは単一ユーザセッションでの使用を意図しており、現在セッションがアクティブな非特権ユーザの所有下でいくつかのファイルシステムを利用できるようにするからです。

通常ユーザーにデバイスの使用を許可する

カーネルドライバがデバイスを初期化する際に、デフォルト状態ではデバイスノードは root:root によって所有され、パーミッションは 600 に設定されます。[1] よって、ドライバがこのデフォルトを変更するか、ユーザー空間の udev ルールがパーミッションを変更しない限り、通常ユーザーはデバイスにアクセスできません。

Udev 値 OWNERGROUPMODE を使って、アクセス権を付与することができます。しかし、全てのユーザーがデバイスを利用できるようにし、なおかつデバイスファイルのモードを過度に寛容にしないようにするのは困難です。Ubuntu では、plugdev というグループを作成して、このグループにデバイスが追加されます。しかし、このアプローチは systemd の開発者達によって推奨されていない [2] だけでなく、Arch の udev ルールに追加されたときにはバグとみなされました (FS#35602)。歴史的に採用されていたもう一つのアプローチは、デバイスのカテゴリ毎に対応する別々のグループを使用するというものです (ユーザーとグループ#systemd 以前のグループ で説明されています)。

Systemd システムにおける最近の推奨されるアプローチは、MODE660 に設定してグループがデバイスを使用できるようにし、uaccess という TAG を付けることです [3]。この特殊なタグにより、udev は動的なユーザー ACL をデバイスノードに適用するようになり、systemd-logind(8) と連携してログイン中のユーザーがデバイスにアクセスできるようにします。以下は、このアプローチを実装する udev ルールの例です:

/etc/udev/rules.d/71-device-name.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="vendor_id", ATTRS{idProduct}=="product_id", MODE="0660", TAG+="uaccess"

ファームウェアプログラマや USB 仮想 comm デバイスにアクセス

以下のルールは users グループのユーザーが AVR マイクロコントローラの USBtinyISP USB プログラマにアクセスできるように設定します:

/etc/udev/rules.d/50-usbtinyisp.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c9f", GROUP="users", MODE="0660"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0479", GROUP="users", MODE="0660"

他のデバイスを使う場合は lsusb を使ってベンダー・プロダクト ID を確認してください。

HDMI ケーブルの抜き差し時に実行

以下の内容でルール /etc/udev/rules.d/95-hdmi-plug.rules を作成します。

ACTION=="change", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/username/.Xauthority", RUN+="/path/to/script.sh"

VGA ケーブル接続時に実行

VGA モニターケーブルが接続されたときに arandr を起動するには以下の内容の /etc/udev/rules.d/95-monitor-hotplug.rules ルールを作成します:

KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/username/.Xauthority", RUN+="/usr/bin/arandr"

ディスプレイマネージャによっては .Xauthority がユーザーのホームディレクトリに保存されないことがあります。その場合 ENV{XAUTHORITY} を修正する必要があります。例えば GDM なら以下のようになります:

$ printenv XAUTHORITY
/run/user/1000/gdm/Xauthority

新しい eSATA ドライブの検知

eSATA ドライブを挿入しても検知されない場合、いくつか試せることがあります。eSATA を挿入したまま再起動してください。もしくは次を実行してください:

# echo 0 0 0 | tee /sys/class/scsi_host/host*/scan

または (AUR から) scsiaddAUR をインストールして次を実行してください:

# scsiadd -s

うまくいけば、あなたのドライブが /dev にあります。ドライブがない場合、次を実行しながら上のコマンドを試して何が起こっているのか確認してください:

# udevadm monitor

内部 SATA ポートを eSATA とする

eSATA ベイや他の eSATA アダブタを接続するとシステムはディスクを内部 SATA ドライブとして認識します。GNOMEKDE はその度に root パスワードを尋ねることになります。以下の udev ルールは指定した SATA ポートを外部 eSATA ポートとして表示させます。これで、USB ドライブと同じように通常の GNOME ユーザーで eSATA ドライブを root パスワードなしでポートに接続することができるようになります。

/etc/udev/rules.d/10-esata.rules
DEVPATH=="/devices/pci0000:00/0000:00:1f.2/host4/*", ENV{UDISKS_SYSTEM}="0"
ノート: eSATA ドライブを接続した後、以下のコマンドを使うことで DEVPATH がわかります (sdb は適宜置き換えてください):
# udevadm info -q path -n /dev/sdb
/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb
# find /sys/devices/ -name sdb
/sys/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb

固定デバイス名の設定

udev は全てのモジュールを非同期にロードするので、初期化される順番は異なってしまいます。この結果デバイスの名前がランダムで変わる可能性があります。udev ルールを追加すれば固定デバイス名を使えます:

ビデオドライバー

ウェブカメラをセットアップするなら、まずウェブカメラ設定を参照してください。

複数のウェブカメラを使うと、例えば motion (video4linux デバイスやウェブカメラから画像を取得するソフトウェアモーション検知プログラム) を使う場合、起動時にビデオデバイスはランダムで /dev/video0..n と割り当てられます。推奨される方法は udev ルールを使って (udev ルールの記述にある例のようにして) シンボリックリンクを作成する方法です。

/etc/udev/rules.d/83-webcam.rules
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1"
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="08f6", SYMLINK+="video-cam2"
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="0840", SYMLINK+="video-cam3"
ノート: /dev/video* 以外の名前を使うと v4l1compat.sov4l2convert.so のプリロードが破壊されます。

プリンター

複数のプリンターを使っている場合、起動時にランダムで /dev/lp[0-9] のデバイスが割り当てられ、CUPS の設定などを破壊してしまいます。

永続的なブロックデバイスの命名と同じように /dev/lp/by-id/dev/lp/by-path の下にシンボリックリンクを作成する、以下のルールを作成することが可能です:

/etc/udev/rules.d/60-persistent-printer.rules
ACTION=="remove", GOTO="persistent_printer_end"

# This should not be necessary
#KERNEL!="lp*", GOTO="persistent_printer_end"

SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
ENV{ID_TYPE}!="printer", GOTO="persistent_printer_end"

ENV{ID_SERIAL}=="?*", SYMLINK+="lp/by-id/$env{ID_BUS}-$env{ID_SERIAL}"

IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", SYMLINK+="lp/by-path/$env{ID_PATH}"

LABEL="persistent_printer_end"

ディスクをシリアルで識別する

特定のディスクデバイス /dev/sdX に対して何らかのアクションを実行するには、 udevadm info /dev/sdX で表示される固有のシリアル ID_SERIAL_SHORT で永久に特定されます。これは、もし見つかったデバイス名があれば、それをパラメータとして渡して説明します。

/etc/udev/rules.d/69-disk.rules
ACTION=="add", KERNEL=="sd[a-z]", ENV{ID_SERIAL_SHORT}=="X5ER1ALX", RUN+="/path/to/script /dev/%k"

USB デバイスでサスペンドから復帰

udev ルールは、マウスやキーボードなどの USB デバイスのウェイクアップ機能を有効にし、マシンをスリープから復帰させるために使用するのに便利です。

ノート: デフォルトでは、USB ホストコントローラはすべてウェイクアップが有効になっています。その状態は cat /proc/acpi/wakeup で確認することができます。この場合、以下のルールは必要ありませんが、例えばウェイクアップ機能を無効にするなど、他のアクションを実行するためのテンプレートとして使用することができます。

まず、USB デバイスのベンダー識別子と製品識別子を特定します。これらは、udev ルールでそれを認識するために使用されます。例えば

$ lsusb | grep Logitech
Bus 007 Device 002: ID 046d:c52b Logitech, Inc. Unifying Receiver

デバイスが接続されている USB コントローラを検索するには:

# grep c52b /sys/bus/usb/devices/*/idProduct
/sys/bus/usb/devices/1-1.1.1.4/idProduct:c52b

デバイスと接続している USB コントローラの power/wakeup 属性を変更してください:

/etc/udev/rules.d/50-wake-on-device.rules
ACTION=="add", SUBSYSTEM=="usb", DRIVER=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", ATTR{power/wakeup}="enabled", ATTR{driver/1-1.1.1.4/power/wakeup}="enabled"

イベントでトリガー実行

様々な udev イベントをトリガーすると便利なことがあります。例えば、リモートマシンで USB デバイスの切断をシミュレートしたいかもしれません。そのような場合は udevadm trigger を使ってください。

# udevadm trigger --verbose --type=subsystems --action=remove --subsystem-match=usb --attr-match="idVendor=abcd"

このコマンドは、ベンダー ID abcd を持つすべての USB デバイスに対して USB remove イベントを発生させます。

udev ルールからデスクトップ通知を行う

udev を介して notify-send の呼び出しを含む外部スクリプトを呼び出します。デスクトップに通知が表示されない時があります 以下は、udev ルールから notify-send が正常に実行されるために、どのファイルにどんなコマンドと環境変数が含まれている必要があるかの例です。

ノート: この例では多くの変数がハードコードされているので、この例を理解したら、それらを移植することを検討してください (例: ユーザーのショートネームではなく $USER)。

1) 以下の udev ルールは、ノートパソコンの電源状態に応じて画面の明るさを変更した際に、通知音を鳴らし、デスクトップ通知を送信するスクリプトを実行するものです。ファイルを作成します。

/etc/udev/rules.d/99-backlight_notification.rules
# Rule for when switching to battery
ACTION=="change", SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="0", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/USERNAME/.Xauthority" RUN+="/usr/bin/su USERNAME_TO_RUN_SCRIPT_AS -c /usr/local/bin/brightness_notification.sh"
# Rule for when switching to AC
ACTION=="change", SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="1", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/USERNAME/.Xauthority" RUN+="/usr/bin/su USERNAME_TO_RUN_SCRIPT_AS -c /usr/local/bin/brightness_notification.sh"
  • USERNAME_TO_RUN_SCRIPT_ASUSERNAME は、通知が表示されるグラフィックセッションのユーザーのショートネームに変更する必要があります。
  • スクリプトは /usr/bin/su で実行する必要があり、これは通知が表示されるグラフィカルセッションのユーザー(root/system ではなく)の下にその所有権を配置します。

2) udev ルールの発動時に実行される実行スクリプトの内容。

/usr/local/bin/brightness_notification.sh
#!/usr/bin/env bash

export XAUTHORITY=/home/USERNAME_TO_RUN_SCRIPT_AS/.Xauthority
export DISPLAY=:0
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/UID_OF_USER_TO_RUN_SCRIPT_AS/bus"

/usr/bin/sudo -u USERNAME_TO_RUN_SCRIPT_AS /usr/bin/paplay --server=/run/user/UID_OF_USER_TO_RUN_SCRIPT_AS/pulse/native /home/USERNAME/.i3/sounds/Click1.wav > /dev/null 2>&1

/usr/bin/notify-send --icon=/usr/share/icons/gnome/256x256/status/battery-full-charging.png 'Changing Power States' --expire-time=4000
  • USERNAME_TO_RUN_SCRIPT_AS, UID_OF_USER_TO_RUN_SCRIPT_AS, USERNAME はユーザーのショートネームと通知を表示するグラフィックセッションのユーザーのUIDに変更する必要があります。
  • pulseaudio 経由でオーディオを再生する場合、/usr/bin/sudo が必要です。
  • 通知が表示されるグラフィカルセッションのユーザーのための3つの環境変数 (すなわち、XAUTHORITY, DISPLAY and DBUS_SESSION_BUS_ADDRESS) を定義してエクスポートすることが必要です。
ヒント: ユーザーのディスプレイ環境変数を取得し、IMPORT キーで udevルールにエクスポートする方法として xpubAUR も参照してください。

3) 新しい udev ルール (上記参照) をロード/リロードして、ノートパソコンの電源を抜いてテストします。

長時間稼働するプロセスの生成

udev によって起動されたプログラムは、そのデバイスからのさらなるイベントをブロックし、udev のルールから生成されたタスクは、イベント処理が完了した後に強制終了されます。udev で長時間稼働するプロセスを起動する必要がある場合、at を使うことができます。(例: your_command | at now, batch) もしくは systemd ユニット から直接 udev ルールからトリガー を作成することも可能です。

トラブルシューティング

モジュールのブラックリスト

稀に、udev が間違って誤ったモジュールをロードすることがあります。これを止めさせるために、モジュールをブラックリストに入れることができます。ブラックリスト化すれば、udev は二度とそのモジュールをロードしません。カーネルモジュール#ブラックリストを見て下さい。起動時と hotplug のイベント時 (例: USB フラッシュドライブを入れた時) 両方です。

デバッグ出力

ハードウェアのデバッグ情報を取得したいときは、udev.log-priority=debug カーネルパラメータを使ってください。もしくは、以下を設定:

/etc/udev/udev.conf
udev_log="debug"

上記の設定ファイルを FILES 行に追加することで initramfs に組み込むこともできます:

/etc/mkinitcpio.conf
FILES="... /etc/udev/udev.conf"

設定後は initramfs を再生成してください:

# mkinitcpio -p linux

起動時に udevd が止まる

LDAP に移行したり LDAP を使っているシステムを更新した後 udevd が起動時 "Starting UDev Daemon" というメッセージを出したときに止まることがあります。これは通常 udevd が LDAP にある名前を検索しようとして、ネットワークがまだ立ち上がっておらず、失敗していることが原因です。解決方法は全てのシステムグループの名前をローカルで存在させることです。

udev ルールで記述されているグループ名とシステム上にあるグループ名を抽出してください:

# fgrep -r GROUP /etc/udev/rules.d/ /usr/lib/udev/rules.d | perl -nle '/GROUP\s*=\s*"(.*?)"/ && print $1;' | sort | uniq > udev_groups
# cut -f1 -d: /etc/gshadow /etc/group | sort | uniq > present_groups

違いを確認するために、side-by-side の diff を実行してください:

# diff -y present_groups udev_groups
...
network							      <
nobody							      <
ntp							      <
optical								optical
power							      |	pcscd
rfkill							      <
root								root
scanner								scanner
smmsp							      <
storage								storage
...

この場合、何らかの理由で pcscd グループがシステム上に存在しません。欠けているグループを追加してください:

# groupadd pcscd

また、LDAP に頼る前にローカルリソースが検索されるようにしてください。/etc/nsswitch.conf に次の行を含める必要があります:

group: files ldap

リムーバブルデバイスとして扱われなくてはならないデバイスがそう扱われない

問題のデバイスのカスタム udev ルールを作成する必要があります。デバイスの定義情報を取得するために ID_SERIAL または ID_SERIAL_SHORT を使います (/dev/sdb は必要に応じて変更してください):

$ udevadm info /dev/sdb | grep ID_SERIAL

それから /etc/udev/rules.d/ にルールを作成して udisks または udisks2 の変数を設定します。

udisks の場合、UDISKS_SYSTEM_INTERNAL="0" を設定することでデバイスがリムーバブルとして扱われるようになり、自動マウントできるようになります (詳しくは udisks(7) を参照):

/etc/udev/rules.d/50-external-myhomedisk.rules
ENV{ID_SERIAL_SHORT}=="serial_number", ENV{UDISKS_SYSTEM_INTERNAL}="0"

udisks2 の場合、UDISKS_AUTO="1" を設定することでデバイスが自動マウントされ、UDISKS_SYSTEM="0" を設定することでデバイスがリムーバブルとして認識されます。詳しくは udisks(8) を参照。

/etc/udev/rules.d/99-removable.rules
ENV{ID_SERIAL_SHORT}=="serial_number", ENV{UDISKS_AUTO}="1", ENV{UDISKS_SYSTEM}="0"

udevadm control --reloadudev ルールをリロードしてください。デバイスを接続すると外付けドライブとして認識されるはずです。

モジュールが自動でロードされないサウンドの問題

/etc/modprobe.d/sound.conf 内の古いエントリによって問題が起こる場合があります。このファイルを手入れして、それから再度試して下さい。

ノート: udev>=171 から、デフォルトで OSS エミュレーションモジュール (snd_seq_oss, snd_pcm_oss, snd_mixer_oss) は自動でロードされなくなりました。

IDE CD/DVD ドライブサポート

バージョン 170 から、udev は CD-ROM/DVD-ROM ドライブをサポートしておらず、伝統的な IDE ドライブとして ide_cd_mod モジュールを使ってロードされ /dev/hd* として表示します。cdparanoia など、ハードウェアに直接アクセスするツールでは問題なくドライブを使えますが、KDE などのより高い次元のユーザースペースのプログラムにはドライブが見えなくなります。

sr_mod など他のモジュールよりも先に ide_cd_mod モジュールがロードされる理由は、何らかの理由で initramfs で piix モジュールをロードしているなどが考えられます。その場合、/etc/mkinitcpio.conf で piix を ata_piix に置き換えることができます。

オプティカルドライブのグループ ID が "disk" に設定される

オプティカルドライブのグループ ID が disk に設定されていて、それを optical に設定したい場合、カスタム udev ルールを作成する必要があります:

/etc/udev/rules.d
# permissions for IDE CD devices
SUBSYSTEMS=="ide", KERNEL=="hd[a-z]", ATTR{removable}=="1", ATTRS{media}=="cdrom*", GROUP="optical"

# permissions for SCSI CD devices
SUBSYSTEMS=="scsi", KERNEL=="s[rg][0-9]*", ATTRS{type}=="5", GROUP="optical"

X サーバーが存在しない場合、RUN ルールの X プログラムがハングする

xrandr または別の X ベースのプログラムが X サーバーに接続しようとすると TCP 接続にフォールバックします。これは、systemd-udev サービス設定IPAddressDeny が原因でハングします。最終的にプログラムは強制終了され、イベント処理が再開されます。

ルールが DRM デバイス用であり、ハングによって X サーバーの起動後にイベント処理が完了する場合、これにより 3D アクセラレーションが failed toauthenticate magic エラーで動作しなくなる可能性があります。

参照