Mount

在 systemd 更新到版本 239 後,用於自動掛載媒體設備的 Udev 規則停止工作

  • August 27, 2018

有一段時間,我有一個有效的 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 個可能有問題的更改:

  1. MountFlags預設設置中未指定該選項。
  2. 有一個新選項PrivateMounts設置為yes

systemd文件中我發現現在我只需要設置PrivateMounts=no和傳播掛載點就可以到達使用者空間。

然而,這種情況並非如此。

我試過了

  1. 改變PrivateMounts=no
  2. 更改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

# /etc/systemd/system/my-mounter@.service
[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 中的新增功能。因此,恢復先前行為的最簡單方法是完全刪除它。

引用自:https://unix.stackexchange.com/questions/464959