最近在Raspbian寫一個(gè)測試程序,硬件是樹莓派3b+。期間要用到Linux udev 自動(dòng)掛載U盤,踩了坑。
我想通過在/etc/udev/rules.d/ 目錄中自定義 一個(gè)10-usb-stick.rules文件來實(shí)現(xiàn)U盤按需自動(dòng)掛載:
# Match the U stick
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", ENV{mount_options}="relatime"
# Filesystem-specific mount options
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002"
# Mount the device
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}"
# 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"
然后執(zhí)行udevadm命令更新rules文件:
udevadm control --reload-rules
插入U(xiǎn)盤后,發(fā)現(xiàn)系統(tǒng)并未掛載成功,訪問掛載點(diǎn)報(bào)錯(cuò):
Transport endpoint not connected errors
通過文檔:https://www.axllent.org/docs/view/auto-mounting-usb-storage/
中的讀者回饋建議得知:
In new Raspbian image they have implemented some security features within systemd-udevd.service.
To execute run command from USB mount udev rule as I started my query
you need to comment last few lines inside
/lib/systemd/system/systemd-udevd.service:
Should look like this:
[Service]
Type=notify
OOMScoreAdjust=-1000
Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket
Restart=always
RestartSec=0
ExecStart=/lib/systemd/systemd-udevd
KillMode=mixed
WatchdogSec=3min
TasksMax=infinity
#MountFlags=slave 注釋該行
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
然后重新加載systemd
systemctl daemon-reload
果然U盤可以按需加載。
查看man手冊(cè)
man 5 systemd.exec
MountFlags=
Takes a mount propagation flag: shared, slave or private, which
control whether mounts in the file system namespace set up for this
unit's processes will receive or propagate mounts or unmounts.
Use slave to run processes so that none of their mounts and unmounts
will propagate to the host. See
mount(2) for details.
man 2 mount
Creating a new mount point
If none of MS_REMOUNT, MS_BIND, MS_MOVE, MS_SHARED, MS_PRIVATE,
MS_SLAVE, or MS_UNBINDABLE is specified in mountflags, then mount()
performs its default action: creating a new mount point.
終于知道原因,原來udev中設(shè)置了掛載標(biāo)志(MountFlags)來控制可移動(dòng)設(shè)備mount消息的傳遞,MountFlags在systemd-udevd.service文件中默認(rèn)是slave,即不傳遞mount消息到文件系統(tǒng)。我的需求是由udev自動(dòng)產(chǎn)生一個(gè)新掛載點(diǎn),所以MountFlags無需賦值,注銷掉即可;而不是像其他文檔所說,需要把mountflages=slave換成mountflages=shared .
ps:如果要關(guān)閉樹莓派圖形系統(tǒng)下自動(dòng)掛載U盤,則

2.

3.

The end.