16

How can I implement udev rules for any USB mass-storage device plugged in, not just for specific one? What should be changed in idVendor, and idProduct?

 ACTION=="add", SUBSYSTEM=="usb", SYSFS{idVendor}=="0204", SYSFS{idProduct}=="6025",
     RUN+="/home/workspace/bash_script.sh"
Toby Speight
  • 8,678

1 Answers1

11

A storage device is in the block subsystem, so you'll want SUBSYSTEM=="block" in your rule, like this:

ACTION=="add", KERNEL=="sd?", SUBSYSTEM=="block", ENV{ID_BUS}=="usb", \
    RUN+="/path/to/script"

If you're using systemd, you could run a systemd unit each time a USB storage device is added. Create the unit file, e.g. /etc/systemd/system/my-usb-rule.service:

[Service]
Type=oneshot
ExecStart=/path/to/script

and the rule, e.g. /etc/udev/rules.d/85-my-usb-rule.rules:

ACTION=="add", KERNEL=="sd?", SUBSYSTEM=="block", ENV{ID_BUS}=="usb", \
    ENV{SYSTEMD_WANTS}="my-usb-rule.service"

Now udev will trigger my-usb-rule.service (which in turn will execute your script) on any usb storage device add event.


Don't forget to reload the configuration after you edit the rules/units:

udevadm control --reload
systemctl daemon-reload
don_crissti
  • 82,805
  • When I add a USB mass storage, I would like to act on the partition(s) it contains. On udev level I can see events from 4 subsystems: usb, scsi, bdi, and block (in this order). The first 3 ones are unusable, because the partition is not yet known. The block event has ID_BUS=scsi, not usb as in your code example. I don't see any suitable attribute in the block event, that would tell me whether it is USB mass storage or not. (Investigation done using udevadm monitor and udevadm info). Unless I could trust that ID_BUS=scsi could not reasonably be anything else but USB mass storage. – Uwe Geuder Jan 16 '17 at 15:53
  • @UweGeuder - nothing stopping you to use the device name as an argument to your program and based on that act on the partitions... – don_crissti Jan 16 '17 at 17:33
  • 1
    Well, in the USB events the device name is something like /dev/bus/usb/002/040. Not sure what to do with that in my program. In the Block events the device name is something like /dev/sdb or /dev/sdb1. That's what I want, but now I'm back to the problem that ID_BUS=scsi. I got a bit further: There is a rules file 80-udisk2, which adds a property ID_DRIVE_THUMB. Not sure how robust it is, there seem to very few vendors listed. My rule file was called 70-*, so as expected my /dev/sdb did not match. Weirdly enough /dev/sdb1 matched, although my rule runs first. – Uwe Geuder Jan 16 '17 at 19:44
  • 1
    Ah I just note the original question was any USB mass storage drive. That should work with the rule SUBSYSTEM=="block", SUBSYSTEMS=="usb" (note the difference with the S). I doubt it can always work with ENV{ID_BUS}=="usb" in the original answer, because I see the value scsi here. But I am working on a slightly different problem than originally asked, I want any USB stick (pendrive), but no external drives. – Uwe Geuder Jan 16 '17 at 20:14
  • 2
    Actually the nasty truth is that ENV{ID_BUS} value is not the same on all systems. Yesterday I was working on an older system with udev 210 (I believe. Cannot check now because the machine is not on the internet), There the value was scsi. Now, I am on newer machine with udev 228 and the value is usb. For the same USB stick, I am carrying it with me. (not sure whether the udev version is the relevant factor here, could also be the kernel or any other package installing udev rules, e,g, udisks2) Still SUBSYSTEM=="block", SUBSYSTEMS=="usb" (note S) might be portable and safe. – Uwe Geuder Jan 17 '17 at 10:21