Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

I'm having trouble with udev rules not running. Here's an example:

I have a rule /etc/udev/rules.d/99-test.rules which contains:

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

And sayhi just has:

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

This being an Intel machine, I obviously have many vendor 0x8086 PCI devices:

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 ]

And yet, when I boot, /saidhi will either not be created at all, or will have 1 or 2 date lines in it.

If, after booting, I run udevadm trigger --action=add --subsystem-match=pci then /saidhi will get exactly the right number of dates added to it.

Why doesn't this work during the boot process?

share|improve this question
1  
My guess is that udev is running so quickly/early that the root filesystem isn't mounted readwrite yet. If so, is there a way to ask a rule not to run until filesystems are ready? (Obviously, the above example is a contrived one; I have a real case where I need to do something to the filesystem when a certain device is detected on boot.) –  dmd Apr 10 '14 at 1:40
    
You could either hardcode in a time to wait, e.g. with sleep 30 or how long is appropriate. Or you could (possibly?) poll to see if the directory exists with [ -e / ]. I'm not sure if you can look at /, so maybe [ -e /tmp ] instead. –  Sparhawk Apr 10 '14 at 1:44
    
Adding sleep 30 before the date line in the sayhi script had no effect; so maybe that's not the problem. –  dmd Apr 10 '14 at 1:55
    
Oh, actually, now I think about it, my comments don't make any sense at all. If / isn't mounted, then the udev script would never be called at all. Do you boot into x? Perhaps it'd be better to run scripts when the GUI loads up? –  Sparhawk Apr 10 '14 at 2:02
1  
The really interesting thing is this works fine on the exact same system, cloned to a slower (spinning, instead of SSD) disk. –  dmd Apr 10 '14 at 3:09

2 Answers 2

I actually have a way that will wait just the right amount of time, not an arbitrary 30sec. I did it on Raspberry Pi to automatically mount all connected USB disks upon connection but also on boot time.

The rule is similar to yours:

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

Now the script is actually a recursive call (and I know this is evil):

$ 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

Note that the "grep 'dev/root'" is specific to Raspbian OS, so on Ubuntu you will need to design your own grep to detect the rootfs (or even better design some universal grep). Notice that the script will call itself in the background and exit and only if the rootfs is "rw" will call the right mounting script. The script "/home/pi/bin/usb-automount.sh" does the actual mounting or in your case the logging.

Note this script still takes 3 seconds to execute, so you may further optimize by changing to:

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

However I never checked that and do not know if this will work as expected (I am no scripting guru).

share|improve this answer

I taught of same cause as @dmd, PCI uevents come before filesystem re-mount as rw. (But sometimes, some of PCI uevents come after, race condition, working in parallel)

dmesg | grep -i -e mount -e pci

@Sparhawk sleep idea seems good to me. I think this why it doesn't work (Ref: man udev):

This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device.

Starting daemons or other long running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.

So, I created new script that start & disown the script that has sleep command. Actually, It does WORK!

$ 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"
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.