29

I'm creating a new basic rule

/etc/udev/rules.d/10-myrule.rules

containing:

KERNEL!="sdb*", GOTO="auto_mount_end"
ACTION=="add", RUN+="/usr/bin/mount /dev/sdb1 /media"
LABEL="auto_mount_end"

I saved, rebooted, and inserted a SD card (recognized by /dev/sdb1, I see it with dmesg), but nothing happens. When I do manually mount /dev/sdb1 /media, it works.

How can I troubleshoot / debug such an udev rule?

Note: I'm using ArchLinux, but it should be the same on any distro?

Basj
  • 2,519

6 Answers6

21

Update

  • Reference: udev_237 - man udev (Ubuntu_18.04)

    RUN{type}

       ︙

      Note that running programs that access the network or mount/unmount filesystems is not allowed inside of udev rules, due to the default sandbox that is enforced on systemd-udevd.service.


Original Answer Debugging hint are valid for other udev rule applications.

  • 10- as mentioned by jasonwryan, use high numbering (90's good). So your rule is not going to be overridden by another one.

  • Use the minimum keys just as you really need. Example, != & GOTO/LABEL, instead use directly ==

      ACTION=="add", KERNEL=="sdb*", RUN+="/usr/bin/mount /dev/sdb1 /media"
    
  • Your target was sdb1 with fixed command, minimize the blind match using KERNEL=="sdb1"

  • I find it useful to create a shadow debugging rule, I called shadow because I always leave it there in same file, so I use it when I need it.

      ACTION=="add", KERNEL=="sdb*", RUN+="/bin/sh -c 'echo == >> /home/user/Desktop/udev-env.txt; env >> /home/user/Desktop/udev-env.txt'"
      #ACTION=="add", KERNEL=="sdb*", RUN+="/usr/bin/mount /dev/sdb1 /media"
    

    Notes:

    • udev-env.txt is created then the rule is triggered anyway. Line == corresponding to one matching node. The ENV recorded in that file could be mixture between 2 node or more, created almost in same time, it's a stdout buffering problem.
    • Some environment variables that showed up in this debug, may not be used for condition because at by that time udev processing matches they are not yet populated (from previous rules). See https://www.suse.com/support/kb/doc/?id=000016106 (Mentioned by @clonejo in comments)
  • Use udevadm monitor -u, udevadm test ... and udevadm trigger ... to verify which rules processed the events.

  • Inside the scripts is up to you to make debug log and catch failed commands, by saving their return value also stdout & stderr messages.

user.dz
  • 1,875
  • 1
    Very useful. A couple of comments udevadm test... appears to only show you environment variables, to gets ATTRS you can use udevadm info $DEVICE to find these other settings. – Att Righ Feb 02 '17 at 18:57
  • 1
    In udevadm info returns a tree of devices be careful to distinguish settings between a device and its parent devices (properties seem to be inherited if not overridden). In my case the subsystem was wrong. – Att Righ Feb 02 '17 at 19:03
  • udevadm test "This program is for debugging only, it does not run any program specified by a RUN key. It may show incorrect results, because some values may be different, or not available at a simulation run." Is there no way to just trace what is actually happening? – MarcH Oct 31 '18 at 00:06
  • @MarcH , you could use udevadm monitor -u to check for events/conditions & udevadm trigger ... to test their actions. – user.dz Oct 31 '18 at 08:42
  • @MarcH , but inside the scripts is up to you to make debug log and catch failed commands (by saving their return value also stdout & stderr messages). – user.dz Oct 31 '18 at 08:50
  • @user.dz the system scripts are not mine and I can't even tell which ones run and which don't. I searched and searched and it looks like no one can tell that. – MarcH Nov 14 '18 at 17:02
  • 1
    Dumping the environment using the dummy rule can have misleading results. Some env vars are only populated by other udev rules, but RUN+= is only executed after all rules have been matched: https://www.suse.com/support/kb/doc/?id=000016106 – clonejo Sep 02 '22 at 18:42
  • Thank you @clonejo , that's interesting pitfall to watch for. Added a note about it to the answer. – user.dz Sep 02 '22 at 22:54
13

This command will allow one to observe the execution of rules:

udevadm control --log-priority=debug
journalctl -f

(and udevadm control --log-priority=info to set it back to sane levels)

eMPee584
  • 327
2

I think the command you're looking for here is udevadm. You'll use the trigger and test parameters to trigger a rescan of the udev events, and to test a specific event, respectively.

I learned this the hard way when putzing around with the new network device naming in EL 7. Good luck!

Paul
  • 371
1
  1. Create a udev rules file

    sudo nano /etc/udev/rules.d/99-removable-sd.rules
    
  2. Add rule that tells udisks to automount it

    SUBSYSTEM=="block", SUBSYSTEMS=="mmc", DRIVERS=="mmcblk", ATTRS{type}=="SD", ENV{UDISKS_AUTO}="1", ENV{UDISKS_SYSTEM}="0"
    

    ATTRS{type}=="SD" may be not required if you are using different types.

  3. Reload rules

    sudo udevadm control -R
    
  4. Eject it then put back.

Reference: Archlinux Wiki: Some devices, that should be treated as removable, are not

user.dz
  • 1,875
1

I was having the same problem with RASPBERRY PI 3 B+, it could be possible that above commands may help you. But it DID NOT help me. I was trying to invoke a script on inserting a USB storage device. The rules do not get logged in syslog, so it becomes very difficult to understand which rule worked or which rule failed.

So I did the following:

(1) I made my rule file in /etc/udev/rules.d/100-myrule.rules

(2) then I ran the command sudo /etc/init.d/udev restart

then I checked it worked. A piece of information, may be useful to you or may not be, but the filesystems are readonly for udev until the command at (2) is executed.

MSharq
  • 21
0

For me, the solution was to enable full event monitoring early in the boot process. On Debian 12 "bookworm":

# vi /usr/share/initramfs-tools/init

find the line where devtmpfs is mounted on /dev, and after that add a line to start udevadm monitor in background:

mount -t devtmpfs -o nosuid,mode=0755 udev /dev
udevadm monitor -k -u -p > /dev/debug-udevadm-monitor.txt &

Then call update-initramfs -u to get the change into /boot/initrd.img-xxxx, and shutdown -r now. After the restart, look in /dev/debug-udevadm-monitor.txt for lines containing FAILED or ERRNO, or any other patterns related to the issue being debugged. In my case the problem event looked like this:

UDEV  [2.582336] add      /devices/pci0000:00/0000:00:19.0/net/eth4 (net)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:19.0/net/eth4
SUBSYSTEM=net
INTERFACE=eth4
IFINDEX=4
SEQNUM=1518
USEC_INITIALIZED=1290728
ID_NET_NAMING_SCHEME=v252
ID_NET_NAME_MAC=enx00224d123456
ID_NET_NAME_ONBOARD=eno1
ID_NET_LABEL_ONBOARD=Intel(R) 82579V Gigabit Network Device
ID_NET_NAME_PATH=enp0s25
ID_BUS=pci
ID_VENDOR_ID=0x8086
ID_MODEL_ID=0x1503
ID_PATH=pci-0000:00:19.0
ID_PATH_TAG=pci-0000_00_19_0
ID_NET_DRIVER=e1000e
ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
ID_NET_NAME=eno1
ID_RENAMING=1
INTERFACE_OLD=eth2
UDEV_WORKER_FAILED=1
UDEV_WORKER_ERRNO=17
UDEV_WORKER_ERRNO_NAME=EEXIST

(that is, one cannot rename eth2 to eth4 because the latter already exists).

sizif
  • 286