systemd 更新到版本 239 后,自动挂载媒体设备的 Udev 规则停止工作

systemd 更新到版本 239 后,自动挂载媒体设备的 Udev 规则停止工作

一段时间以来,我有一个有效的 udev 规则来自动挂载媒体设备。

/etc/udev/rules.d/61-mount_media_by_label.rules

#
# To propagate udev's mountpoint to the user space, MountFlags must have a value "shared" in the /usr/lib/systemd/system/systemd-udevd.service.
#

# Ignore devices that aren't storage block-devices and block-devices that are already listed in /etc/fstab.
KERNEL!="sd[a-z][1-9]*", GOTO="mount_media_by_label_end"
PROGRAM="/bin/grep -e '^UUID=%E{ID_FS_UUID}' /etc/fstab", RESULT!="", GOTO="mount_media_by_label_end"

# Decide the name for device's mountpoint directory, based on device's label.
ENV{ID_FS_LABEL}!="", ENV{mountpoint}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{mountpoint}="usb-%k"

# If device is being plugged in, set options for mount command.
ACTION=="add", ENV{mount_options}="relatime"
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="%E{mount_options},utf8,gid=100,umask=002"

# If device is being plugged in, create mountpoint directory in /media and mount device node to it.
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{mountpoint}", RUN+="/bin/mount -o %E{mount_options} /dev/%k /media/%E{mountpoint}"

# If device is being plugged out, unmount it and delete its mountpoint directory.
ACTION=="remove", ENV{mountpoint}!="", RUN+="/bin/umount -l /media/%E{mountpoint}", RUN+="/bin/rmdir /media/%E{mountpoint}"

# Label for early exit.
LABEL="mount_media_by_label_end"

MountFlags为了使这个规则发挥作用,我只需将option的值更改为sharedin
/usr/lib/systemd/system/systemd-udevd.service
当我更新systemd到版本后239,这个文件看起来不一样了。
我注意到两个可能有问题的变化:

  1. MountFlags默认设置中未指定该选项。
  2. 有一个新选项PrivateMounts设置为yes

来自systemd文档我想现在我只需要设置PrivateMounts=no并且安装点的传播就会到达用户空间。

然而,这种情况并非如此。
我努力了

  1. 改变PrivateMounts=no
  2. 更改PrivateMounts=no和添加MountFlags=shared

但两者都不起作用。

从udev规则中及以后挂载媒体设备的正确方法是什么systemd v239

答案1

这种方法可能不是最佳的。例如,如果您支持使用挂载可写NTFS ntfs-3g,则ntfs-3g每当您重新启动udev时,该进程都会被终止。

请注意,现代安全理论建议台式机应该开始使用 FUSE 进行安装全部可移动文件系统。 https://lwn.net/Articles/755593/

如果您能弄清楚如何启动(和停止?)一个单独的 systemd 单元……并将其写为首选方法,那么在任何特殊文档中不断建议 Arch 用户使用此模式:-) 那就更好了。使用单独的 systemd 单元将避免应用于 udev 服务的限制。

例如,使用 启动 systemd 作用域单元中的命令systemd-run --no-block --scope -- my mount command here

很遗憾,如果您希望包含的单元ntfs-3g具有可识别的名称,100% 正确的方法是什么并不是很明显。如果具有该名称的旧单元仍然被跟踪为“活动”,但进程刚刚退出,那么简单地要求服务启动不会执行任何操作。您可以忽略该问题,为名称生成随机后缀,或者尝试排除这一系列事件......但也许有更好的方法。

我还没有使用 FUSE 对此进行测试,但我认为执行此操作的方法是命令systemd-mount

A超级用户答案建议systemd-mount在 udev 规则仍在运行时在设备上使用可能无法正常工作。这需要相当巴洛克的解决方法。 (RUN+="/path/to/my/script %k"运行systemd-run --no-block --scope --unit=mount-$1 sh -c "systemctl start /dev/$1; systemd-mount ...")。

我认为这样做的方法看起来像

ENV{SYSTEMD_WANTS}=my-mounter@%k.service

# /etc/systemd/system/[email protected]
[Service]
Type=oneshot
ExecStart=systemd-mount %I

#!/bin/sh
# /usr/local/lib/my-mounter
# You can make this as complicated as you want.
# (Although curiously systemd-mount also reads SYSTEMD_MOUNT_WHERE and
# SYSTEMD_MOUNT_OPTIONS properties if you set them on the udev device.)
# You could also read udev properties yourself using 
# eval "$(udevadm info --query=property --export)"

DEVNAME="$1"
systemd-mount "/dev/$DEVNAME"

默认值会systemd-mount导致文件系统在删除时自动卸载,但之后不会清除自动创建的挂载点目录(!)。


v239 中的两个单独更改-您必须恢复以获得旧行为的单独指令。

  1. PrivateMounts=yes。将其替换为PrivateMounts=no.
  2. SystemCallFilter=@system-service @module @raw-io

    该指令的使用是 v239 中的新增内容。因此,恢复以前的行为的最简单方法就是完全删除它。

相关内容