用于挂载磁盘的 Udev 规则不起作用

用于挂载磁盘的 Udev 规则不起作用

我在 /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"

运行后:

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

它什么也不做。但是,如果我更改 /bin/touch /tmp/xyz 等内容的挂载命令,它就可以工作。

版本:

[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) 

答案1

Ubuntu 18.04 中也会出现同样的问题,其根本原因相同。为了修复它,我们创建一个覆盖文件systemd-udevd

sudo systemctl edit systemd-udevd

并插入:

[Service]
MountFlags=shared

(在 Ubuntu 20.04 上,替换MountFlags=sharedPrivateMounts=no.)

保存文件然后执行:

sudo systemctl daemon-reload
sudo service systemd-udevd --full-restart

答案2

这是一个 systemd 功能。原来的udev命令已被替换为systemd-udevd(参见其手册页)。区别之一是它创建自己的文件系统命名空间,因此挂载已完成,但它在主体命名空间中不可见。 (您可以通过systemctl status systemd-udevd获取服务的主 PID,然后查看/proc/<pid>/mountinfo文件系统的内容来检查这一点)。

如果您想恢复使用共享文件系统名称空间而不是私有文件系统名称空间,请创建一个/etc/systemd/system/systemd-udevd.service包含内容的文件

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

/etc/systemd/system/systemd-udevd.service.d/myoverride.conf或仅包含最后两行的新目录和文件,即

[Service]
MountFlags=shared

并重新启动 systemd-udevd 服务。我还没有发现这样做的后果。

答案3

虽然目前有一些解决方案基于设置 MountFlags(如前面的答案中所述),但我担心的是,鉴于开发人员似乎过去更改了默认设置,他们可能会在将来彻底删除它,以便获得他们对绝对权力的持续追求有更多的控制力。

所以,这是我的替代解决方案:在 /usr/local/bin 中,将以下内容放入文件 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"

然后放入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
) &

并使其可执行。

放入文件/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

然后执行 sudo systemctl enable uysdmd.service 最后执行 sudo systemctl restart systemd-udevd

现在可以像从 udev 挂钩挂载一样使用 uysdm 程序。

这将创建一个守护进程,该守护进程正在侦听从 uysdm 命令接收到的执行挂载请求。

它确实依赖于串行处理的 udev 事件,而不是同时处理,我认为情况就是如此。

相关内容