一段时间以来,我有一个有效的 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的值更改为shared
in
/usr/lib/systemd/system/systemd-udevd.service
当我更新systemd
到版本后239
,这个文件看起来不一样了。
我注意到两个可能有问题的变化:
MountFlags
默认设置中未指定该选项。- 有一个新选项
PrivateMounts
设置为yes
。
来自systemd
的文档我想现在我只需要设置PrivateMounts=no
并且安装点的传播就会到达用户空间。
然而,这种情况并非如此。
我努力了
- 改变
PrivateMounts=no
- 更改
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 中的两个单独更改-二您必须恢复以获得旧行为的单独指令。
PrivateMounts=yes
。将其替换为PrivateMounts=no
.SystemCallFilter=@system-service @module @raw-io
该指令的使用是 v239 中的新增内容。因此,恢复以前的行为的最简单方法就是完全删除它。