Writing udev rules

Using udev can ease your life with using external units, such as memory sticks or removable storage devices which many of us use these days. On a personal note, I have a few memory sticks that I use quite often, as well as Western Digital USB HDD I use for backup purposes. Having to manually mount these every time I plug them in, is rather tedious task so I thought about a method to get this done automatically. And here comes our friend udev in for play. The purpose of udev is to manage your /dev entries, so that it becomes more manageable. To quote kernel.org on udev;

udev allows Linux users to have a dynamic /dev directory and it provides the ability to have persistent device names.

First things first, we need to find some information about the unit in question. In this case I want to get information about my USB HDD, which I know is has the dev entry of /dev/sdc.

luna:/dev# udevinfo -q path -n /dev/sdc
/block/sdc

Reading this, we now know that the information is found under /sys/block/sdc. Let’s move on.

luna:/dev# udevinfo -q all -p /sys/block/sdc
P: /block/sdc
N: sdc
S: mybook
S: disk/by-id/usb-WD_2500JB_External_57442D5743414E4B38343139353830
S: disk/by-path/pci-0000:00:1d.7-usb-0:2:1.0-scsi-0:0:0:0
E: ID_VENDOR=WD
E: ID_MODEL=2500JB_External
E: ID_REVISION=0108
E: ID_SERIAL=WD_2500JB_External_57442D5743414E4B38343139353830
E: ID_TYPE=disk
E: ID_BUS=usb
E: ID_PATH=pci-0000:00:1d.7-usb-0:2:1.0-scsi-0:0:0:0

As we can read from this, we see that there’s an attribute that uniquely identifies this hard drive. The attribute is called «ID_SERIAL». This attribute is what we will use in our udev rule. Let us now proceed to make the actual udev rule.

vim /etc/udev/rules.d/local.rules

I take caution into making a new rules file called «local.rules» to make things more manageable for both myself, but more importantly so that apt doesn’t touch my rule sets when udev might be upgraded in the future.

BUS=="usb", KERNEL=="sd*", ENV{ID_SERIAL}="WD_2500JB_External_57442D5743414E4B38343139353830", NAME="%k", SYMLINK="mybook%n"

An explanation of the above rule

BUS==”usb”
# The unit in question is plugged into the USB bus.
KERNEL==”sd*”
# The system mounts the unit to /dev/sdc as mentioned above.
ENV{ID_SERIAL}
# This is the serial number we got from using «udevinfo» earlier on.
NAME=”%k”
# I have to admit that I’m a bit uncertain what this bit does, but I know that it has to be there.
SYMLINK=”mybook%n”
# This is the name of the symlink we want created when the unit is plugged in.

And that’s all there is to it. Hope this guide was understandable and helpful. And good luck!

Update
As it turns out, udev has certain problems with the above rule set when you attach more than one USB unit that uses the usb-storage sub system. The reason is that udev doesn’t see «ENV{ID_SERIAL} for some obscure reason. Why this is the case eludes me, but I’ve found a workaround.

udevinfo -a -p `udevinfo -q path -n /dev/sdc` | grep serial

Which will yield the following:

ATTRS{serial}=="57442D5743414E4B38343139353830"

On some system, ATTRS are reported as SYSFS, but pay no attention to that. In udev rule sets, SYSFS must be used at all times, as ATTRS isn’t a recognizable parameter in udev. The new and updated rule set would then be as follows:

BUS=="usb", KERNEL=="sd*", SYSFS{serial}=="57442D5743414E4B38343139353830", NAME="%k", SYMLINK="mybook%n"
Writing udev rules
Tagged on:                                                             

2 thoughts on “Writing udev rules

  • July 22, 2008 at 12:03
    Permalink

    Hiya,

    Excellent article, just what I was looking for. Just thought I’d let you know, man udev reveals that the %k is the kernel device name – sdc in this case, and the %n is the “number” aka partition, which would be 1 for sdc1.
    There’s a few other substitution parameters in there as well, very handy for fine-tuning custom udev rules.
    Thanks!!

    Reply
  • December 9, 2010 at 10:40
    Permalink

    Great article, thank you and Baltho!

    Reply

Leave a Reply