17

I tried to create some udev rules to mount and unmount my USB flash drives; the rules for the moment are very simple:

ACTION=="add",KERNEL=="sd[b-z]",RUN+="/root/scripts/plug_flash_drive.sh %k"
ACTION=="remove",KERNEL=="sd[b-z]",RUN+="/root/scripts/unplug_flash_drive.sh %k"

plug_flash_drive.sh is also very simple:

device_name=$1
mount_options="umask=000,utf8"
if [ ! -e "/media/$device_name" ]; then
    mkdir "/media/$device_name"
fi
sleep 1
/usr/bin/mount "/dev/$device_name" "/media/$device_name" -o "$mount_options"

unplug_flash_drive.sh:

device_name=$1

umount "/dev/$device_name"
rmdir "/media/$device_name"

I have done some tests so I can ascertain that:

  • When plugged in, my flash drive is detected; a file is created in /dev
  • plug_flash_drive.sh is called by udev
  • the mkdir part of the script works
  • however, it seems that the "mount" part of the script is not executed, so my drive is not mounted
  • when I call my scripts on the command line, they perfectly work

Does anybody know why mount is not executed when called by udev?

EDIT 28/08/14: I added "grep -q /proc/mounts && echo success || echo failure" at the end of my script to check in my debug log if the device is actually mounted before the script ends. It appears that the device is mounted at that point even when the script is called by udev. So the real problem is now "my block device is seemingly unmounted after the mount script end when called through udev" :s

7
  • This may be beside the point, but why do you mkdir "$mount_dir" but rmdir "/media/$device_name"? Where is $mount_dir set? Aug 27, 2014 at 20:22
  • sorry, this is a typo, I used some quite useless variables aliasing in the original codes and I removed them here for the sake of clarity
    – magva
    Aug 27, 2014 at 20:26
  • Have you tried old-school debugging; e.g., by putting set -xv and exec >> "$HOME"/mount.log 2>&1 into the .sh files? Aug 27, 2014 at 20:43
  • 1
    I have done that, but according to the log I get, mount is executed when the script is called by udev. There is no difference in the log between a call from udev and from command line... that's actually rather baffling
    – magva
    Aug 27, 2014 at 21:11
  • 1
    in that case, the script would also fail when run from command line
    – magva
    Aug 27, 2014 at 22:48

4 Answers 4

22

systemd-udevd runs in its own file system namespace and by default mounts done within udev .rules do not propagate to the host. To make your old scripts work you can set MountFlags=shared in /usr/lib/systemd/system/systemd-udevd.service or (better) creating and editing its copy at /etc/systemd/system/

See man 5 systemd.exec for more information, MountFlags option.

2
  • What do you mean by "do not propagate to the host"?
    – sebelk
    Dec 13, 2016 at 16:01
  • 2
    @sebelk I believe user83388 means they don't propagate to the "root" namespace
    – Mark
    Jun 7, 2017 at 19:17
4

As of this writing, the other answers are incorrect (or out of date).

You should not run mount from a Systemd service. Even after commenting the MountFlags and PrivateMounts lines in systemd-udevd.service, your rule will not work for FUSE filesystems like NTFS or exFAT, because the FUSE process will get helpfully killed by Systemd.

See this ArchWiki page which lists several better options. My preference is a tiny project on GitHub called udev-media-automount, which simply restarts a Systemd service from the Udev rule. This is a convenient way to get around Udev's various cumbersome restrictions on namespaces and child processes.

See also this anwser, which shows how to use the SYSTEMD_WANTS Udev variable to start a Systemd unit.

0

You can use systemd-mount to mount block devices with a udev rule. Example of auto-mounting the Raspberry Pi Pico derived from the ArchWiki page mentioned by @Metamorphic (note that you need to make /mnt/pico ahead of time:

ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", RUN+="/usr/bin/logger --tag rpi-pico-mount Mounting what seems to be a Raspberry Pi Pico", RUN+="/usr/bin/systemd-mount --no-block --collect -o gid=users,fmask=113,dmask=002 $devnode /mnt/pico"

The post mentions adding the flag --automount=yes, but this caused remount problems for me.

Make sure to reload the udev rules so your changes take effect:

sudo udevadm control --reload

Adding the logger message to the rule helped with debugging. You can see it get printed by watching journalctl -f. It's useful to start with a generic match pattern, then build up to something more specific.

-1

You could try to use := instead of += in the rules RUN assignments.

The := operator sets the list value and disallows further changes.

3
  • thanks, but mount still not works :(
    – magva
    Aug 27, 2014 at 20:33
  • 1
    Maybe not your case, but in my system mount is located at /bin/mount. Try "command -v mount".
    – xae
    Aug 27, 2014 at 21:04
  • 1
    In my system, the path returned by "command -v mount" is /usr/bin/mount. I noticed that I also had a /bin/mount executable, but it doesnt work either when called by udev
    – magva
    Aug 27, 2014 at 21:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .