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?

8
  • 1
    Have you restarted udev after adding the 80-usb.rules file? systemctl restart udev.service
    – drs
    Commented Apr 23, 2013 at 2:08
  • Have you tried making a script that executes the touch command and setting RUN to the path to the script?
    – drs
    Commented Apr 23, 2013 at 2: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
    Commented Apr 23, 2013 at 4: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
    Commented Apr 23, 2013 at 15:59
  • 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
    Commented Apr 24, 2013 at 5:55

2 Answers 2

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"
4
  • 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
    Commented Jan 4, 2016 at 18:36
  • 1
    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
    Commented Jan 4, 2016 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
    Commented Jan 4, 2016 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
    Commented May 20, 2019 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'
1
  • 1
    it just can run the script not a command
    – mohammad
    Commented Nov 6, 2013 at 13:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .