有一段时间,我有一个有效的 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
选项的值更改shared
为
/usr/lib/systemd/system/systemd-udevd.service
在我更新systemd
到 version后239
,这个文件看起来就不同了。
我注意到 2 个可能有问题的更改:
MountFlags
默认设置中未指定该选项。- 有一个新选项
PrivateMounts
设置为yes
。
从systemd
的文档中我发现现在我只需要设置PrivateMounts=no
和传播挂载点就可以到达用户空间。
然而,这种情况并非如此。
我努力了
- 改变
PrivateMounts=no
- 更改
PrivateMounts=no
和添加MountFlags=shared
但两者都不起作用。
systemd v239
从 udev 规则及以后安装媒体设备的正确方法是什么?
这种方法可能不是最理想的。例如,如果您支持使用 挂载可写 NTFS ,则每当您重新启动 udev 时
ntfs-3g
,该ntfs-3g
进程都会被终止。请注意,现代安全原则建议桌面应开始使用 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
命令。超级用户的回答表明,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
导致文件系统在删除时自动卸载的默认值
systemd-mount
,但它们不会在之后清理自动创建的安装点目录(!)。v239 中有两个单独的更改-您必须恢复两个单独的指令才能获得旧的行为。
PrivateMounts=yes
. 将此替换为PrivateMounts=no
.SystemCallFilter=@system-service @module @raw-io
此指令的使用是 v239 中的新增功能。因此,恢复先前行为的最简单方法是完全删除它。