13

I have the following content in in /etc/udev/rules.d/81-external-disk.rules:

ENV{ID_FS_UUID}=="6826692e-79f4-4423-8467-cef4d5e840c5", RUN{program}+="/bin/mount -o nofail,x-systemd.device-timeout=1 -t ext4 -U 6826692e-79f4-4423-8467-cef4d5e840c5 /backup/external"

After running:

udevadm control --reload ; udevadm trigger /dev/sdb1

It does nothing at all. However if II change the mount command for something such as /bin/touch /tmp/xyz it works.

Versions:

[root@helsinki rules.d]# rpm -qa | grep udev
libgudev1-219-19.el7_2.12.x86_64
python-pyudev-0.15-7.el7_2.1.noarch
[root@helsinki rules.d]# rpm -qa | grep systemd
systemd-libs-219-19.el7_2.12.x86_64
systemd-219-19.el7_2.12.x86_64
systemd-sysv-219-19.el7_2.12.x86_64
[root@helsinki rules.d]# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core) 

3 Answers 3

22

This same problem occurs in Ubuntu 18.04 with the same underlying cause. To fix it we create an override file for systemd-udevd:

sudo systemctl edit systemd-udevd

And insert into it:

[Service]
MountFlags=shared

(on Ubuntu 20.04, replace MountFlags=shared with PrivateMounts=no.)

Save the file and then execute:

sudo systemctl daemon-reload
sudo service systemd-udevd --full-restart
5
  • It worked like a charm on Raspberry (Raspbian 9 "stretch"). Thanks! Oct 24, 2018 at 19:07
  • 2
    It did not work for my Ubuntu 18.04 to solve the problem of no automount for USB drive.
    – Yu Shen
    Jan 12, 2019 at 15:41
  • Worked in Ubuntu 18.04. @YuShen, you might want to check your udev rules.
    – Greg Bell
    Feb 15, 2020 at 1:54
  • 3
    On Ubuntu 20.04, this didn't work for me. Changing MountFlags=shared to PrivateMounts=no did.
    – Mikel
    Jun 23, 2020 at 0:13
  • This doesn't work for me. I tried both options, and each individually. The disk automatically unmounts immediately after it is said to be mounted. However, manually calling mount -a works a treat...
    – Climax
    Nov 30, 2022 at 8:45
21

This is a systemd feature. The original udev command has been replaced by systemd-udevd (see its man page). One of the differences is that it creates its own filesystem namespace, so your mount is done, but it is not visible in the principal namespace. (You can check this by doing systemctl status systemd-udevd to get the Main PID of the service, then looking through the contents of /proc/<pid>/mountinfo for your filesystem).

If you want to go back to having a shared instead of private filesystem namespace, then create a file /etc/systemd/system/systemd-udevd.service with contents

.include /usr/lib/systemd/system/systemd-udevd.service
[Service]
MountFlags=shared 

or a new directory and file /etc/systemd/system/systemd-udevd.service.d/myoverride.conf with just the last 2 lines, i.e.

[Service]
MountFlags=shared

and restart the systemd-udevd service. I haven't found the implications of doing this.

3
  • Yes I've applied such a workaround, I wonder if has security implications too.
    – sebelk
    Dec 13, 2016 at 19:52
  • 1
    Pretty sure this did not work until I added [Service] between those two lines.
    – goldilocks
    Oct 15, 2017 at 23:10
  • 1
    @goldilocks You are probably right. I added this to the answer, thanks. It might depend on what the last section was in the included file, but it seems systemd now prefers you to use the *.d/*.conf way of making changes, as .include doesnt seem to be documented.
    – meuh
    Oct 16, 2017 at 7:54
1

While there are are solutions that currently work based setting the MountFlags as described in earlier answers, my concern is that given that the developers appear to have change the default setting in the past, they may just remove it outright in the future so as to get yet more control in their continuing drive for absolute power.

So, here's my alternative solution: In /usr/local/bin place the following into the file uysdm

#!/bin/bash
umask 077
rp=`mktemp -d /tmp/uysd_XXXXX`
if [ $? != 0 ]; then
        exit 1
fi
mkfifo $rp/fifo

echo $rp/fifo "$*" >/var/uysd/fifo &
X=$!
res=`cat $rp/fifo`
stat=$?
rm -rf "$rp"
wait $X
if [ $? != 0 ]; then
        exit $?
fi
exit "$res"

Then put into file uysdmd

#!/bin/bash
# Up yours systemd mount daemon

if [ ! -e /var/uysd/fifo ]; then
        umask 0077
        mkdir -p /var/uysd
        mkfifo /var/uysd/fifo
fi

(
        while true; do (
                IFS=" "
                read rp mt </var/uysd/fifo
                if [ "$mt" = "" ]; then
                        exit 1
                fi
                echo "$mt" | xargs mount >&2
                echo $? >"$rp"
        ) done
) &

And make it executable.

Put into file /lib/systemd/system/uysdmd.service

[Unit]
Description=Up Yours Systemd udev mount daemon

[Service]
ExecStart=/usr/local/bin/uysdmd
Type=forking

[Install]
WantedBy=systemd-udevd.service

Then do sudo systemctl enable uysdmd.service Finally do sudo systemctl restart systemd-udevd

Now the uysdm program can be used like mount from the udev hook.

This creates a daemon that is listening for requests to perform mounts that it receives from the uysdm command.

It does rather depend on the udev events being handled serially, rather than concurrently, which I believe is the case.

You must log in to answer this question.

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