Ubuntu

與udev鬥爭

  • November 23, 2019

我想automount在 Ubuntu 上使用我的 SD 卡。udevadm我使用(或)嘗試了以下規則/lib/systemd/systemd-udevd

KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"
# Import FS infos
IMPORT{program}="/sbin/blkid -o udev -p %N"
# Get a label if present, otherwise specify one
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k"
# Global mount options
ACTION=="add|change", ENV{mount_options}="relatime"
# Filesystem-specific mount options
ACTION=="add|change", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002"
# Mount the device
ACTION=="add|change", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}", RUN+=" echo /bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name\
} > /tmp/debug_out.txt"
#ACTION=="add|change"
# Clean up after removal
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"
# Exit
LABEL="media_by_label_auto_mount_end"

程式碼來自網路。

`udevadm monitor` indicates that the card is detected

KERNEL[1778159.935932] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
KERNEL[1778159.939553] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)
KERNEL[1778159.942501] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
KERNEL[1778159.942615] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)
UDEV  [1778160.026230] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
UDEV  [1778160.101285] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)
UDEV  [1778160.184648] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
KERNEL[1778160.320013] add      /kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(14341:systemd-udevd.service) (cgroup)
UDEV  [1778160.322555] add      /kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(14341:systemd-udevd.service) (cgroup)
KERNEL[1778160.387280] add      /kernel/slab/fat_inode_cache/cgroup/fat_inode_cache(14341:systemd-udevd.service) (cgroup)
UDEV  [1778160.388849] add      /kernel/slab/fat_inode_cache/cgroup/fat_inode_cache(14341:systemd-udevd.service) (cgroup)
UDEV  [1778160.418509] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)

並且輸出udevadm test /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1看起來也不錯

[...]
run: '/bin/mkdir -p /media/usbhd-sdc1'
run: '/bin/mount -o relatime /dev/sdc1 /media/usbhd-sdc1'
run: '/usr/bin/unshare -m /usr/bin/snap auto-import --mount=/dev/sdc1'
[...]

但是,規則只創建目錄而不掛載卡。使用權限手動執行上述規則可以sudo按預期工作(無法創建目錄,sudo因此這不是問題)

(小後續問題:我想從卡中復製文件,觸發作業和unmount卡。我也應該這樣做unmount還是使用不同的機制)

========================

如下所述更改了所有內容:

Udev/rules.d

KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"

ACTION=="add", SUBSYSTEM=="block",TAG+="systemd", ENV{SYSTEMD_WANTS}=sd-automounter@%k.service
ACTION=="change", SUBSYSTEM=="block",TAG+="systemd", RUN+="systemctl start sd-automounter@%k"
# Clean up after removal  
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"  
# Exit  

服務說明

# /etc/systemd/system/sd-automounter@.service
[Service]
Type=oneshot
ExecStart=/usr/local/libexec/sd-automounter %I(base)

和服務

#!/bin/sh
# /usr/local/libexec/sd-automounter
echo "" > /tmp/debug.out
DEVICE_NAME=/dev/"$1"
echo $DEVICE_NAME >>/tmp/debug.out
udevadm info --query=property --export $DEVICE_NAME >> /tmp/debug.out
echo "" >> /tmp/debug.out
CARD_NAME=$(udevadm info --query=property --export $DEVICE_NAME | grep ID_FS_LABEL= | awk -F\' '{print $2}')
echo $CARD_NAME >> /tmp/debug.out
#CARD_NAME=$(/sbin/blkid  | grep "$DEVICE_NAME" | awk -F\" '{print $2}' |sed 's/ /_/g')
udevadm info --query=property --export /dev/sdc1
echo $CARD_NAME
mkdir -p /media/$CARD_NAME
mount -t vfat $DEVICE_NAME /media/$CARD_NAME
thanks for all help in advance

手動執行它systemctl start sd-automounter@sdd1就像一個魅力。

udevadm monitor但是在顯示時刪除和插入什麼也沒發生

monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[1977111.519970] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
KERNEL[1977111.523252] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)
KERNEL[1977111.526457] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
KERNEL[1977111.526572] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)
UDEV  [1977111.612257] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
UDEV  [1977111.614914] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)
UDEV  [1977111.697870] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
UDEV  [1977111.791344] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)

第二個選項的問題是我必須使用完整路徑

ACTION=="add", SUBSYSTEM=="block",TAG+="systemd", RUN+="/bin/systemctl start sd-automounter@%k"
ACTION=="change", SUBSYSTEM=="block",TAG+="systemd", RUN+="/bin/systemctl start sd-automounter@%k"

並使用執行選項也添加

systemd-udev 真的不希望您再直接從規則掛載文件系統。你可以在這個網站上找到很多關於它的問題:-)。

在最新版本的 systemd 中,udev 服務文件具有SystemCallFilter=@system-service @module @raw-io. 這不允許掛載文件系統所需的系統呼叫。

(此外,我相信如果您直接用於 FUSE 文件系統,則與 systemd 存在普遍衝突,mount例如ntfs-3g。如果您啟動 FUSE 伺服器程序,最好將它放在專用的 systemd 單元中,例如.mount單元。如果您讓 FUSE 程序留在您目前的單元內,那麼 FUSE 程序的生命週期將與您正在執行的單元的生命週期耦合)。

為了避免將來(或目前)中的命令出現問題RUN+=,您的規則可以改為使用ENV{SYSTEMD_WANTS}=my-automounter@%k.service, 然後

# /etc/systemd/system/my-automounter@.service
[Service]
Type=oneshot
ExecStart=/usr/local/libexec/my-automounter %I
#!/bin/sh
# /usr/local/libexec/my-automounter

DEV=/dev/"$1"

# You can make this script as complicated as you want.
# You can read udev properties if you want, using 
# eval "$(udevadm info --query=property --export "$DEV")"
...

如果您想測試手動呼叫該單元,您可以使用systemctl start my-automounter@sdc1.

systemctl status my-automounter@*如果 systemd 執行您的腳本時發生錯誤,您可以使用, 或.查看錯誤消息journalctl -b -u my-automounter@*

這也避免了您必須處理udev特定的錯誤報告。我認為兩者sh都有systemd有用的錯誤報告,以防程序突然死亡。例如,他們應該報告一個程序是否被信號殺死SIGSYS,因為它試圖呼叫一個已被阻止使用的系統呼叫SystemCallFilter=:-)。

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