49

What is the state-of-the-art method for automatically executing custom scripts upon USB device plug-in under current Linux distributions like Debian/CentOS/Fedora?

For example if you want to automatically mount/copy some files/umount a USB mass storage device based on its UUID (or device ID etc.).

Kevin
  • 40,767
maxschlepzig
  • 57,532

2 Answers2

35

Put a line like this in a file in /etc/udev/rules.d:

KERNEL=="sd*", ATTRS{vendor}=="Yoyodyne", ATTRS{model}=="XYZ42", ATTRS{serial}=="123465789", RUN+="/pathto/script"

Add a clause like NAME="subdir/mydisk%n" if you want to use a custom entry path under /dev.

Run udevadm info -a -n sdb to see what attributes you can match against (attribute=="value"; replace sdb by the device name automatically assigned to the disk, corresponding to the new entry created in /dev when you plug it in). Note that you can use ATTRS clauses from any one stanza: you can pick any stanza, but the ATTRS clauses must all come from the same stanza, you can't mix and match. You can mix ATTRS clauses with other types of clauses listed in a different stanza.

  • 1
    Is this answer still valid? Under no amount of fiddling can I get the script to execute (and touch a file). If you can provide the most basic example that executes a script when anything is plugged in, that would be great and we can work from there. – Redsandro Feb 22 '13 at 15:00
  • @Redsandro I have variations of this rule in my udev configuration and they're working. Did you plug the device out and back in, or run udevadm trigger? Does your system use udev? If you want to run a script when anything is plugged in, remove all the conditions (the clauses with ==) (maybe the syntax requires one condition, I'm not sure; if it does, use KERNEL=="*"). – Gilles 'SO- stop being evil' Feb 22 '13 at 15:28
  • I tried that too, but since it works for you, I must be missing a step. I have moved this question here, so I can write example code. – Redsandro Feb 22 '13 at 15:36
  • Perhaps related, I think there is a time limit on how long the script may run. I believe it is very short (like 1 second or something). If it takes longer than that, then udev will kill it. You can work around this by using backgrounding the script with something like at. See "running external programs" on http://www.reactivated.net/writing_udev_rules.html – cheshirekow Jun 03 '18 at 01:15
  • 2
    Just to add to this, for the sake of completeness, the file needs to have the suffix .rules and the files in the directory are read in a lexical order (convention uses numeric prefix to order them), and they can be beneath /etc/, /usr/lib or /run. For more, RTFM. – starfry Dec 21 '18 at 09:19
19

I looked in /lib/udev/rules.d for examples of disk related rules. On an Ubuntu system one rule file provides the environment variable ID_FS_UUID_ENC which you can use in own rule files.

Thus I put a custom rule file under /etc/udev/rules.d/foodevice.rules. Since it is not prefixed with a number, it is ran at last by udev. Btw, the udev daemon watches /etc/udev/rules.d for changes such that you don't need to restart it on file changes.

The content of /etc/udev/rules.d/foodevice.rules is:

ACTION=="add", KERNEL=="sd*[!0-9]", ENV{ID_FS_UUID_ENC}=="FFFF-AAAF",
  RUN+="/usr/bin/sudo -u juser /home/juser/path/script.sh"

(this is one rule - you have to remove the newline after the ENV clause because udev does not have a line continuation mechanism)

A program started by udev blocks the daemon - thus it shouldn't run for a long time. I solved it via at - i.e. via detaching from the process doing the real work:

$ cat /home/juser/path/script.sh
#!/bin/sh
echo /path/to/mountcopystuff.sh | at now
maxschlepzig
  • 57,532