5

I'm running RHEL6 and I'm trying to write a udev rule that is triggered upon plugging in and removing usb devices. I created a file called 80-usb.rules in /etc/udev/rules.d/ and I gave it the following contents (so far nothing too specific, just want to test):

ACTION=="add", SUBSYSTEMS=="usb", RUN+="touch /tmp/test"

I saved the file and plugged in a USB drive to test. However, the file /tmp/test was not created.

I figure my udev rule should match my USB drive, since I can run udevadm info on the USB drive and at least one of the parent devices has the attribute SUBSYSTEMS=="usb".

Why might the udev rule not get triggered?

I tried to run udevadm test --action=add /path/to/device and it is clear that the .rules file that I wrote is being processed and that my rules are being matched. Here are a few relevant lines from the output:

parse_file: reading '/etc/udev/rules.d/80-usb.rules' as rules file
udev_rules_apply_to_event: RUN '/bin/touch /tmp/test' /etc/udev/rules.d/80-usb.rules:1
udevadm_test: run: '/bin/touch /tmp/test'

But still, /tmp/test does not exist. I am so confused. Clearly this rule is being matched and the rules are being applied. So why doesn't the command specified by RUN execute?

Braiam
  • 35,991
jayhendren
  • 8,384
  • 2
  • 33
  • 58
  • 1
    Have you restarted udev after adding the 80-usb.rules file? systemctl restart udev.service – drs Apr 23 '13 at 02:08
  • Have you tried making a script that executes the touch command and setting RUN to the path to the script? – drs Apr 23 '13 at 02:18
  • 2
    The rule might have write permissions to write in /, but if you are not sure about that, at least while experimenting you should touch /tmp/udevfile – Anthon Apr 23 '13 at 04:11
  • Thanks for the help guys, but none of your suggestions got me closer to a solution, unfortunately. udev isn't actually a service on my machine (udev-post is, but restarting that won't and doesn't help any). Writing to /tmp/ is a good idea though. I don't know why I wasn't writing there before. Brain fart, I guess. – jayhendren Apr 23 '13 at 15:59
  • @drs Udev monitors the /etc/udev directory, you don't need to notify it when you've changed or added a rule file unless you've put a symbolic link there to a file that's outside /etc/udev. – Gilles 'SO- stop being evil' Apr 24 '13 at 01:29
  • 1
    Thanks Gilles. I'm at a total loss here. When I run udevadm monitor I can clearly see the add and remove events when I plug/unplug my USB stick. But when I put the udev event attributes found using this method into a udev rule, I cannot get the rule to trigger and the command specified with RUN+="..." to run. I've even tried manually triggering with udevadm trigger. – jayhendren Apr 24 '13 at 05:55
  • @jayhendren did you ever resolve this issue? I've got a similar configuration on Debian that does work as expected. Happy to compare notes. – Chris Davies May 01 '15 at 13:12
  • I think I did, but to be honest, it's been a couple years and I don't really remember well. This was just a little toy that I was working on, and I don't have the box around any more. – jayhendren May 01 '15 at 21:14

2 Answers2

3

Your rule must give an absolute path for executable:

ACTION=="add", SUBSYSTEMS=="usb", RUN+="/usr/bin/touch /tmp/test"

Edit:

And if you want to execute a script, you must tell what shell will execute it:

ACTION=="add", SUBSYSTEMS=="usb", RUN+="/bin/sh /path/to/your/script"
Mathieu
  • 2,719
  • Hmm, I don't think that's the issue. touch resolves to /bin/touch according to the posted debug output. What's your source for "Your rule must give an absolute path for executable"? – jayhendren Jan 04 '16 at 18:36
  • 1
    http://www.freedesktop.org/software/systemd/man/udev.html "Execute an external program specified as the assigned value. If no absolute path is given, the program is expected to live in /usr/lib/udev; otherwise, the absolute path must be specified." – Mathieu Jan 04 '16 at 19:53
  • 1
    Ah. The man page you linked to appears to come from systemd, but the question specifically asks about RHEL 6, which does not have systemd. I checked the man page for udev on RHEL 6, and no dependency on an absolute path to a program is given there. – jayhendren Jan 04 '16 at 21:41
  • Thanks for pointing out the path and env issue. My script was missing the #!/bin/bash at the beginning of the same ant that was the issue. – rkachach May 20 '19 at 15:39
1

You have to ensure the following:

  • Paths in the RUN command should be absolute
  • The file has to be executable
  • The PATH environment is limited within the execution of you command

At first add this script file to /lib/udev/touch.sh

vim /lib/udev/touch.sh

in that file write:

#!/bin/bash
touch /tmp/test

make it executable:

chmod +x /lib/udev/touch.sh

and change your rules file to:

ACTION=="add", SUBSYSTEMS=="usb", RUN+="/lib/udev/touch.sh"

reload your udev rules

udevadm control --reload-rules

This will read your rules in /lib/udev/rules.d/* again. Changes will not apply until now.

Note that udev executes your script with a reduced PATH environment. You have to ensure that any binary that's not within the configured paths has to be accessed with a full path. You could also extend the PATH environment within your script.

Check what path is defined by logging the set output to a log file from your wrapper script:

set >>/tmp/udev-env-test

It might look like this:

PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'