udev
関連記事
- "udev とは、Linuxカーネル 用のデバイス管理ツールである。主に
/dev
ディレクトリ以下のデバイスノードを管理するために利用する。以前/dev
ディレクトリの管理を担っていた devfs と、ホットスワップやファームウェアのロードなどユーザー空間におけるデバイスのアクション全てを担っていた hotplug の後継ツールである。"
udev
は hotplug
と hwdetect
両方の機能を置き換えます。
Udev は並列処理を利用してカーネルモジュールをロードするため順番にモジュールをロードするのと比べ良いパフォーマンスが得られます。従ってモジュールは非同期に読み込まれます。この方法の欠点として、起動した時 udev はいつも同じ順番ではモジュールをロードしません。マシンに複数のブロックデバイスがある場合、デバイスノードの名称がランダムに変化する可能性があります。例えば、マシンに2つハードドライブが接続されている場合、ランダムで /dev/sda
が /dev/sdb
になるかもしれません。これについては下で詳しく説明しています。
インストール
現在 Udev は systemd に含まれているため Arch Linux ではデフォルトでインストールされています。詳しくは systemd-udevd.service(8) の man ページを見て下さい。
AUR には独立したフォークが存在します: eudev。
udev ルールについて
Udev ルールは管理者によって書かれます。/etc/udev/rules.d/
を見て下さい、ファイルの名前は .rules
で終わる必要があります。様々なパッケージに udev ルールが含まれており /usr/lib/udev/rules.d/
に保存されます。同じ名前のファイルが /usr/lib
と /etc
に存在する場合は、/etc
内のファイルが優先されます。
udev ルールを記述する
- udev ルールの書き方を学ぶには udev ルールの書き方 (日本語訳) を見て下さい。
- udev ルールのサンプルを見るには Improved Udev Rule For Arch Linux を見て下さい。
以下はウェブカメラが接続されたときにシンボリックリンク /dev/video-cam1
を作るルールの例です。まず、カメラが接続されたときデバイス /dev/video2
にロードされていることを見つけたとします。このルールを書く理由は次のブート時にデバイスが /dev/video0
など他の名前で表示される可能性があるからです。
# udevadm info -a -p $(udevadm info -q path -n /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"
を使います、そして usb parent SUBSYSTEMS=="usb"
, ATTRS{idVendor}=="05a9"
, ATTRS{idProduct}=="4519"
から製造者・製品 ID を使ってウェブカメラをマッチさせます。
/etc/udev/rules.d/83-webcam.rules
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", \ ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1"
上の例では SYMLINK+="video-cam1"
を使ってシンボリックリンクを作成していますが OWNER="john"
や GROUP="video"
を使ってユーザーやグループを設定したり MODE="0660"
を使ってパーミッションを設定することも簡単にできます。
ただし、デバイスが取り除かれた時に何かを実行するルールを書く時は、デバイスの属性にアクセス出来ないことに注意してください。この場合、プリセットのデバイス環境変数を使う必要があります。これらの環境変数を監視するには、デバイスを抜いた時に次のコマンドを実行してください:
# udevadm monitor --environment --udev
このコマンドの出力の中に、ID_VENDOR_ID
や ID_MODEL_ID
などの、前に使っていた属性 "idVendor" と "idProduct" に一致する値があるはずです。デバイスの環境変数を使うルールは以下のようになります:
/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 デバイスのフルパスを使用する必要があります。モニターモードを起動し、 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 test $(udevadm info -q path -n [device name]) 2>&1
このコマンドは新しいルールの全てのアクションを実行はしませんが、既存のデバイスのシンボリックリンクのルールは処理します。ロードできないときに役に立つかもしれません。また、テストしたい udev ルールのデバイスのパスを直接指定することも可能です:
# udevadm test /sys/class/backlight/acpi_video0/
新しいルールをロードする
udev はルールファイルの変更を自動的に検出するので、udev を再起動することなく、変更は直ちに有効になります。しかし、既に存在するデバイスに対しては、ルールは自動的に再トリガされません。USB デバイスのようなホットプラグ可能なデバイスは、おそらく新しい規則を有効にするために再接続するか、少なくとも ohci-hcd と ehci-hcd カーネルモジュールをアンロードして再ロードし、それによってすべての USB ドライバを再ロードしなければならないでしょう。
ルールが自動的にリロードされない場合。
# udevadm control --reload
手動で udev にルールを強制的に起動させるには。
# udevadm trigger
Udisks
Udisks を見て下さい。
ヒントとテクニック
ファームウェアプログラマや 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 を確認してください。
USB 挿入で実行
Udisks または devmon ラッパースクリプト を参照してください。
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 ドライブとして認識します。GNOME や KDE はその度に 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"
固定デバイス名の設定
udev は全てのモジュールを非同期にロードするので、初期化される順番は異なってしまいます。この結果デバイスの名前がランダムで変わる可能性があります。udev ルールを追加すれば固定デバイス名を使えます:
- ブロックデバイスは永続的なブロックデバイスの命名を見て下さい。
- ネットワークデバイスはネットワーク設定#デバイス名を見て下さい。
iscsi デバイス
scsi_id からの出力をテストしてください:
# /usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/sdb 3600601607db11e0013ab5a8e371ce111
/etc/udev/rules.d/75-iscsi.rules
#The iscsi device rules. #This will create an iscsi device for each of the targets. KERNEL=="sd*", SUBSYSTEM=="block", \ PROGRAM="/usr/lib/udev/scsi_id --whitelisted --replace-whitespace /dev/$name", \ RESULT=="3600601607db11e0013ab5a8e371ce111", \ NAME="isda"
ビデオドライバー
ウェブカメラをセットアップするなら、まずウェブカメラ設定を参照してください。
複数のウェブカメラを使うと、例えば 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/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"
USB デバイスでサスペンドから復帰
最初に、あなたのデバイスの製造者・製品 ID を見つけて下さい、例えば:
# 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 が間違って誤ったモジュールをロードすることがあります。これを止めさせるために、モジュールをブラックリストに入れることができます。ブラックリスト化すれば、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
ハードウェアの既知の問題
BusLogic デバイスが壊れて起動中にフリーズする
これはカーネルのバグでありまだ修正されていません。
リムーバブルデバイスとして扱われなくてはならないデバイスがそう扱われない
問題のデバイスのカスタム 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 --reload
で udev ルールをリロードしてください。デバイスを接続すると外付けドライブとして認識されるはずです。
自動ロードの既知の問題
モジュールが自動でロードされないサウンドの問題
/etc/modprobe.d/sound.conf
内の古いエントリによって問題が起こる場合があります。このファイルを手入れして、それから再度試して下さい。
カスタムカーネルの既知の問題
Udev が全く起動しない
あなたのカーネルバージョンが 2.6.32 以上であることを確認してください。それ以前のカーネルでは udev が自動ロードをするのに必要な uevent をサポートしていません。
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"