Custom udev rules and external program debugging

In udev rules, the %k, %b, %n variables are nice and all, but you can also use the variables you’re comparing and setting such as ID_FS_TYPE, KERNEL, SUBSYSTEM, PHYSDEVPATH, etc.

Within a rule, you can compare against them with ENV{VARIABLE} without a dollar sign. And within a RUN or PROGRAM statement, you can access them with the dollar sign.

usb-thumbdrive

RUN

When you run a command in a udev rule, there’s nothing stopping you from calling a shell and executing a few commands without actually calling a standalone script to do the dirty work like the example above. This makes it more portable as you only need the rule file. No external programs necessary.

SUBSYSTEM==”usb”, $ENV{ID_FS_LABEL}==”vfat”, RUN+=”sh -c ‘if [ ! -d /media/$ENV{ID_FS_LABEL} ]; then mkdir /media$ENV{ID_FS_LABEL}; fi’”

Depending on your version of udev (and if you’re running in verbose mode), you may get warnings about unknown keys. If you get this, it might be because you’re comparing against DEVTYPE instead of ENV{DEVTYPE}. The rule is completely ignoring your comparison, and will match regardless of what you thought the variable should have equaled.

[2511] add_to_rules: unknown key ‘ID_FS_USAGE’ in /etc/udev/rules.d/51-rootninja-storage.rules:2
[2511] add_to_rules: unknown key ‘DEVNAME’ in /etc/udev/rules.d/51-rootninja-storage.rules:2
[2511] add_to_rules: unknown key ‘ID_TYPE’ in /etc/udev/rules.d/51-rootninja-storage.rules:3
[2511] add_to_rules: unknown key ‘PHYSDEVBUS’ in /etc/udev/rules.d/51-rootninja-storage.rules:3

This is bad because although you may continue to match with the rule, the behavior is not as expected. If you were relying on the unknown key to filter out unwanted matches, you fail.

Try killing udevd and run it in the foreground with –debug or –verbose depending on your version of udev. This can help with problems especially in the external program. A misplaced quote or missing semi-colon in a perl script will screw you up.

# ps -ef | grep udevd
root 364 1 0 May17 ? 00:00:00 /sbin/udevd -d
# kill -9 364
# udevd –debug
udev_device_new_from_syspath: device 0×86cc900 has devpath ‘/devices…
udev_watch_restore: restoring old watch on ‘/dev/sdb5′
udev_watch_begin: adding watch on ‘/dev/sdb5′
main: initialize max_childs to 375

In addition to telling you whats going on each step of the way, it will also increase the messages written to syslog.

PROGRAM

If you write out the array of environment variables from inside an external program, you can get a better understanding of just which part of the device discovery is matching your rule and getting processed. It also gives you an idea of just what other data is out there for you to interact with so you can pick and choose what to do in your custom perl script.

#!/usr/local/bin/perl

open( FILE, “>>/tmp/udevout” );
#open( FILE, “>>/dev/null”);

foreach $key (sort keys(%ENV))
{
print FILE “$key=$ENV{$key}\n”;
}

Try executing the program above in a udev rule with a match on SUBSYSTEM==”usb” and you’ll see how it changes. The rule is pretty simple:

SUBSYSTEM==”usb”, PROGRAM=”/usr/local/bin/printenv.pl”

Plug in a usb drive with one partition on it and you’ll match that rule for the device and again for each partition. If you follow up with another rule matching ACTION==”add”, you’ll see you’re matching multiple times too.

Each time the rule matches, the set of environment variables will change.

Other helpful commands:

# udevadmn monitor –environment
# udevinfo -a -p /sys/class/net/eth0
# udevinfo -a -p /sys/block/sdb
# udevinfo -a -p $(udevinfo -q path -n /dev/sdb)

Posted by admica   @   27 May 2010

Related Posts

Like this post? Share it!

Digg Twitter StumbleUpon Delicious Technorati Facebook RSS

2 Comments

Comments
Dec 9, 2011
9:51 am

My dear good man,

Yours is the best udev post out there. I have been googling for the past 3 days non-stop 14 hrs a day. Well, the pain has finally paid off thanks to your post.

Keep it up man.
~Philby

Jan 21, 2012
3:47 pm
#2 DTB :

Good!
In my debian Perl found #!/usr/bin/perl, change or comment the PROGRAM first line:
#!/usr/local/bin/perl OR #!/usr/bin/perl

Leave a Comment

Name

Email

Website

Previous Post
« Google’s playable Pacman videogame without Flash
Next Post
Force gui updates during long callbacks or internal operations in pygtk or gtk »
Powered by Wordpress   |   Lunated designed by ZenVerse