Почему запускаются мои правила udev, если я использую триггер udevadm, но НЕ во время загрузки?

У меня проблемы с тем, что правила udev не работают. Вот пример:

У меня есть правило /etc/udev/rules.d/99-test.rules который содержит:

ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x8086", RUN+="/sayhi"

А также sayhi просто имеет:

#!/bin/bash
date +"%Y-%m-%d %H:%M:%S,%3N" >> /saidhi

Поскольку это машина Intel, у меня, очевидно, есть много PCI-устройств 0x8086:

root@imtrobot:~# lspci -n |grep 8086
00:00.0 0600: 8086:2770 (rev 02)
00:02.0 0300: 8086:2772 (rev 02)
00:1d.0 0c03: 8086:27c8 (rev 01)
[ etc. 12 lines total ]

И все же, когда я загружаюсь, /saidhi либо не будет создан вообще, либо будет содержать 1 или 2 строки даты.

Если после загрузки я запускаю udevadm trigger --action=add --subsystem-match=pci затем /saidhi получите правильное количество дат, добавленных к нему.

Почему это не работает во время процесса загрузки?

3 ответа

Как уже упоминалось, процессы, начатые udev"s RUN= Директива должна быть кратковременной. Я хотел бы предложить еще один более простой способ отделить длительный процесс от udev с помощью системного планировщика at команда:

ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x8086", RUN+="/usr/bin/at -M -f /sayhi now"

Просто убедитесь, что ваш /sayhi сценарий /bin/sh совместимый - это оболочка, которая at использует.

У меня действительно есть способ, который будет ждать нужное количество времени, а не произвольные 30 секунд. Я сделал это на Raspberry Pi, чтобы автоматически подключить все подключенные USB-диски при подключении, а также при загрузке.

Правило похоже на ваше:

$ sudo cat /etc/udev/rules.d/10-usb_automount.rules 
KERNEL=="sd*", RUN+="/home/pi/bin/usb-automount"

Теперь скрипт на самом деле является рекурсивным вызовом (и я знаю, что это зло):

$ cat /home/pi/bin/usb-automount
#!/bin/sh

ROOT_RW=`mount | grep 'dev/root' | grep -E '\(.*rw.*\)'`

if [ -z "$ROOT_RW" ]; then
 sleep 3 
 /home/pi/bin/usb-automount & disown
else
 /home/pi/bin/usb-automount.sh
fi

Обратите внимание, что "grep 'dev/root'" специфичен для Raspbian OS, поэтому в Ubuntu вам нужно будет создать свой собственный grep для обнаружения rootfs (или даже лучше создать какой-нибудь универсальный grep). Обратите внимание, что скрипт будет вызывать себя в фоновом режиме и завершать работу, и только если rootfs имеет значение "rw", вызовет правильный сценарий монтирования. Скрипт "/home/pi/bin/usb-automount.sh" выполняет фактическое монтирование или, в вашем случае, ведение журнала.

Обратите внимание, что выполнение этого скрипта по-прежнему занимает 3 секунды, поэтому вы можете оптимизировать его, выбрав:

if [ -z "$ROOT_RW" ]; then
 ( sleep 3; /home/pi/bin/usb-automount ) & disown
else
 /home/pi/bin/usb-automount.sh
fi

Однако я никогда не проверял это и не знаю, будет ли это работать должным образом (я не гуру сценариев).

Я учил той же причине, что и @dmd, PCI-события происходят до того, как файловая система перемонтируется как rw, (Но иногда некоторые из событий PCI наступают после состояния гонки, работающего параллельно)

dmesg | grep -i -e mount -e pci

@Sparhawk sleep Идея мне кажется хорошей. Я думаю, что это почему-то не работает (Ref: man udev):

Это можно использовать только для очень коротких задач переднего плана. Выполнение обработки события в течение длительного периода времени может заблокировать все дальнейшие события для этого или зависимого устройства.

Запуск демонов или других длительных процессов не подходит для udev; разветвленные процессы, отсоединенные или нет, будут безоговорочно уничтожены после завершения обработки события.

Итак, я создал новый скрипт, который запускает & disown скрипт, который имеет sleep команда. На самом деле, это работает!

$ ls -l /sa*
-rw-r--r-- 1 root root 1104 Oct 24 12:37 /saidhi
-rwxr-xr-x 1 root root   29 Oct 24 12:31 /sayhi
-rwxr-xr-x 1 root root   62 Oct 24 12:28 /sayhi2

$ cat /sayhi
#!/bin/bash
/sayhi2 & disown

$ cat /sayhi2 
#!/bin/bash
sleep 30
date +"%Y-%m-%d %H:%M:%S,%3N" >> /saidhi

$ cat /etc/udev/rules.d/99-test.rules 
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x8086", RUN+="/sayhi"
Другие вопросы по тегам