在 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
選項的值更改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
# /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 中有兩個單獨的更改-您必須恢復兩個單獨的指令才能獲得舊的行為。
PrivateMounts=yes
. 將此替換為PrivateMounts=no
.SystemCallFilter=@system-service @module @raw-io
此指令的使用是 v239 中的新增功能。因此,恢復先前行為的最簡單方法是完全刪除它。