Warum werden meine udev-Regeln ausgeführt, wenn ich den udevadm-Trigger verwende, jedoch NICHT beim Booten?

7

Ich habe Probleme mit nicht laufenden udev-Regeln. Hier ist ein Beispiel:

Ich habe eine Regel, /etc/udev/rules.d/99-test.rulesdie enthält:

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

Und hat sayhieinfach:

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

Da es sich um eine Intel-Maschine handelt, habe ich offensichtlich viele Hersteller von 0x8086-PCI-Geräten:

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 ]

Und doch wird beim Booten /saidhientweder gar nichts erstellt oder es werden 1 oder 2 Datumszeilen darin sein.

Wenn nach dem Booten, laufe ich udevadm trigger --action=add --subsystem-match=pci dann /saidhi erhalten genau die richtige Anzahl von Terminen hinzugefügt.

Warum funktioniert das während des Startvorgangs nicht?

Daniel
quelle
1
Ich vermute, dass udev so schnell / früh läuft, dass das Root-Dateisystem noch nicht readwrite gemountet ist. Wenn ja, gibt es eine Möglichkeit, eine Regel zu bitten, erst ausgeführt zu werden, wenn die Dateisysteme bereit sind? (Offensichtlich ist das obige Beispiel ein erfundenes; ich habe einen realen Fall, in dem ich etwas mit dem Dateisystem tun muss, wenn ein bestimmtes Gerät beim Booten erkannt wird.)
Daniel
1
Sie können entweder in einer Wartezeit fest codieren, z. B. mit sleep 30oder wie lange dies angemessen ist. Oder Sie könnten (möglicherweise?) Abfragen, ob das Verzeichnis mit existiert [ -e / ]. Ich bin mir nicht sicher, ob du es dir ansehen kannst /, also vielleicht [ -e /tmp ]stattdessen.
Sparhawk
Das Hinzufügen sleep 30vor der dateZeile im sayhiSkript hatte keine Auswirkung. Vielleicht ist das nicht das Problem.
Daniel
Oh, eigentlich, jetzt denke ich darüber nach, meine Kommentare ergeben überhaupt keinen Sinn. Wenn /nicht gemountet, wird das udev-Skript niemals aufgerufen. Booten Sie in x? Vielleicht ist es besser, Skripte auszuführen, wenn die GUI geladen wird?
Sparhawk
1
Das wirklich Interessante ist, dass dies auf genau demselben System funktioniert, das auf eine langsamere (sich drehende, statt SSD) Festplatte geklont wurde.
Daniel

Antworten:

1

Ich habe tatsächlich einen Weg, der genau die richtige Zeit wartet, keine willkürlichen 30 Sekunden. Ich habe es auf Raspberry Pi gemacht, um alle angeschlossenen USB-Festplatten beim Anschließen, aber auch beim Booten automatisch zu mounten.

Die Regel ähnelt Ihrer:

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

Jetzt ist das Skript tatsächlich ein rekursiver Aufruf (und ich weiß, dass dies böse ist):

$ 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

Beachten Sie, dass "grep 'dev / root'" spezifisch für Raspbian OS ist. Unter Ubuntu müssen Sie also Ihr eigenes grep entwerfen, um die rootfs zu erkennen (oder noch besser ein universelles grep). Beachten Sie, dass sich das Skript im Hintergrund aufruft und beendet und nur dann, wenn rootfs "rw" ist, das richtige Mounting-Skript aufruft. Das Skript "/home/pi/bin/usb-automount.sh" übernimmt die eigentliche Bereitstellung oder in Ihrem Fall die Protokollierung.

Beachten Sie, dass die Ausführung dieses Skripts noch 3 Sekunden dauert. Sie können es also weiter optimieren, indem Sie zu Folgendem wechseln:

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

Ich habe das jedoch nie überprüft und weiß nicht, ob dies wie erwartet funktioniert (ich bin kein Skript-Guru).

Fëamarto
quelle
Kannst du nicht einfach das ganze else...Teil entfernen und nur das lassen if...fi?
Dr. Beco
1

Wie von anderen erwähnt, sollten die von udevder RUN=Richtlinie gestarteten Prozesse kurzfristig sein . Ich möchte eine andere einfachere Möglichkeit vorschlagen, um einen lang laufenden Prozess mithilfe des System Scheduler- Befehls zu entkoppeln :udevat

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

Stellen Sie einfach sicher, dass Ihr /sayhiSkript /bin/shkompatibel ist - dies ist die verwendete Shell at.

Alex P.
quelle
0

Ich habe aus dem gleichen Grund wie @dmd unterrichtet, PCI-Ereignisse kommen vor dem erneuten Mounten des Dateisystems als rw. (Aber manchmal kommen einige PCI-Ereignisse nach, Rennbedingung, arbeiten parallel)

dmesg | grep -i -e mount -e pci

@ Sparhawk sleepIdee scheint mir gut. Ich denke deshalb funktioniert es nicht (Ref :) man udev:

Dies kann nur für sehr kurz laufende Vordergrundaufgaben verwendet werden. Das Ausführen eines Ereignisprozesses über einen längeren Zeitraum kann alle weiteren Ereignisse für dieses oder ein abhängiges Gerät blockieren.

Das Starten von Daemons oder anderen lang laufenden Prozessen ist für udev nicht geeignet. Die getrennten oder nicht getrennten gegabelten Prozesse werden nach Abschluss der Ereignisbehandlung bedingungslos beendet.

Also habe ich ein neues Skript erstellt, das startet und disowndas Skript, das den sleepBefehl hat. Eigentlich funktioniert es!

$ 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"
user.dz
quelle