Writing udev rules, short notes

Today I was connecting a second USB harddrive to my NSLU2.

What you get is a few interesting effects, among them device IDs (/dev/sda, sdb…) changing depending on the order in which you attach the drives. Plus, I added a USB hub, which makes the device names change anyway.

udev plus tux, from the udev pageThe solution for the crazily jumping dev nodes is the udev system, which is part of Linux for quite a while now, but I never really had a need to play with it yet. But the howto is pretty nice and easy to apply.

Still, a few notes:

  • The SYSFS{whatever} rules support wildcards, so that you don’t have to write the whole descriptor if you don’t want to. For example, “Max*” instead of “Maxtor 6” works totally fine. — That’s especially useful since SYSFS{model} descriptors often seem to be filled up with a couple of spaces at the end.
  • Some (all?) USB hard drives in fact don’t consider themselves to be USB devices. So in this case defining BUS=="usb" will not result in any device links to be created at all. I had to define BUS=="scsi" instead. You should look at the udevinfo output as suggested in the “writing udev rules” howto, it will tell you exactly what setup is necessary for your device/drive configuration.

That’s how my two new rules look like (each in one line only):

BUS==”scsi”, KERNEL==”sd*”, SYSFS{vendor}==”Maxtor*”, SYSFS{model}==”L250R0*”, NAME=”%k”, SYMLINK=”usbhd/maxtor250%n”
BUS==”scsi”, KERNEL==”sd*”, SYSFS{vendor}==”Maxtor*”, SYSFS{model}==”Y080P0*”, NAME=”%k”, SYMLINK=”usbhd/maxtor80%n”

If you have any questions, let me know.

If not, have fun :)



9 Responses to “Writing udev rules, short notes”

  1. 1
    Dan Says:

    Another (possibly easier) way to get at the disk you want is to use ext2 labels. You give a filesystem a label, and then refer to it during mounting via the label instead of the device name. This also survives if you have to replace the machine/OS; the label info is stored in the filesystem itself, whereas the udev conf is specific to that OS instance.

    Of course, if you’re not using ext2 (or ext3), you can’t use ext2 labels.

    Yet another way to overcome devices switching about might be to use LVM. This isn’t quite as transparent as ext2 labels, tho. You’ll have to activate volume groups when you plug in drives. It’ll be transparent across reboots and OS’s, though.

    – Dan

  2. 2
    Fred Says:

    Dan, thanks for the additional info. I like the idea to use device labels. While udev rules are perfect for USB printers / scanners etc., for mounting block devices instead, the label solution seems to be much easier.

  3. 3
    Zoobave Says:

    if i want to run a particular application whenever an USB is plugged, what i have to do with udev and how can i write its rules?

  4. 4
    Fred Says:

    Zoobave: You want to read the udev howto to find that out. It is very detailed and shows you what udev can do and how you can make it do what you want.

  5. 5
    Zoobave Says:

    i did, but, i couldn’t understand where to write . my program is in “/usr/local/zoobave/start”.
    i want to start this application, whenever i insert any USB devices. Where i put these entries? is their any need to restart or reload udev?

  6. 6
    Fred Says:

    The rules files live in /etc/udev/rules.d, as written in the “files” part of the howto.

    And yes you will need to reload the udev rules (or reboot if you like), which they describe in the testing section. Hope this helps!

  7. 7
    Zoobave Says:

    finally, i put the following entry in “/etc/udev/rules.d/01-local.rules” file.

    SUBSYSTEM==”usb_device”, ACTION==”add”, ATTRS{manufacturer}==”JetFlash”, PROGRAM=”/usr/bin/nautilus ”, NAME=”%c”, MODE=”0777″

    if i test using then following command, the nautilus starts

    dvm@dvm-desktop:~$ udevtest /sys/class/usb_device/usbdev4.5/

    parse_file: reading ‘/etc/udev/rules.d/00- init.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/01-local.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/05-options.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/10- myrule.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/20-names.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/25-dmsetup.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/25- iftab.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/30-cdrom_id.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/40-permissions.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/45- fuse.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/45-hplip.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/45-libgphoto2.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/45- libsane.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/50-xserver-xorg-input-wacom.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/60-libpisock.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/60- symlinks.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/65-persistent-input.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/65-persistent-storage.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/80-programs.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/85-alsa.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/85-brltty.rules ‘ as rules file
    parse_file: reading ‘/etc/udev/rules.d/85-hdparm.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/85-hplj10xx.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/85-hwclock.rules ‘ as rules file
    parse_file: reading ‘/etc/udev/rules.d/85-ifupdown.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/85-pcmcia.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/90- modprobe.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/95-hal.rules’ as rules file
    parse_file: reading ‘/etc/udev/rules.d/99-udevmonitor.rules’ as rules file
    This program is for debugging only, it does not run any program,
    specified by a RUN key. It may show incorrect results, if rules
    match against subsystem specfic kernel event variables.

    main: looking at device ‘/class/usb_device/usbdev4.5′ from subsystem ‘usb_device’
    run_program: ‘/usr/bin/nautilus ‘
    run_program: ‘/usr/bin/nautilus’ returned with status 0
    udev_rules_get_name: rule applied, ‘usbdev4.5′ becomes ‘’
    run_program: ‘usb_device_name –export usbdev4.5′
    run_program: ‘/lib/udev/usb_device_name’ (stdout) ‘USB_BUS=004′
    run_program: ‘/lib/udev/usb_device_name’ (stdout) ‘USB_DEV=005′
    run_program: ‘/lib/udev/usb_device_name’ returned with status 0
    run_program: ‘check_ptp_camera 06/01/01′
    run_program: ‘/lib/udev/check_ptp_camera’ returned with status 1
    udev_device_event: device node creation supressed
    main: run: ’socket:/org/freedesktop/hal/udev_event’
    main: run: ’socket:/org/kernel/udev/monitor’

    but, when i insert the same device, it will not run the program automatically. How can i modify the above entry to run the nautilus (or any program) automatically?

  8. 8
    Walt R Says:

    I have been fighting udev for a while, and can not figure out how to write a udev rule that works with ppp0. In order to access the Internet, I manually entered: ln -s /dev/ppp /dev/ppp0

    Thank you, Walt

  9. 9
    toxic Says:

    Zoobave, replace PROGRAM==”/path/to/prog” with RUN+=”/path/to/prog” and it should work given that your other matching rules are in place. Don’t forget to reload the config either.

Leave a Reply