使用udev实现插入U盘自动挂载的一些记录

2019-06-10 遇到的一点小问题
新需求是在U盘插入设备时实现自动挂载功能,一般都是推荐使用udev。记录一下第一次使用出现的问题。

.

刚开始先按网上找的方法
,在/etc/udev/rules.d/创建个.rules文件,再根据插入动作调用.sh文件来执行mount操作:

KERNEL=="sd[a-z]*",ACTION=="add",RUN+="/srv/wannoo.sh %k"

语法挺简单的,就是容易遇坑:有一次KERNELACTION顺序弄反,然后就执行失败;还有一U盘只能读到sdd,所以KERNEL=="sd[a-z][1-9]"读不到,为了兼容只能改成KERNEL=="sd[a-z]"*;然后换行也要注意;还有就是一行命令数限制五个,多了后面的不生效。
不过虽然把语法弄懂了,但mount还是出错了:

mount: /tmp/sdc1: permission denied.
echo $? == 32    #分区不支持挂载是返回这个,随便输个地址也返回这个,服了。

FUSE exfat 1.3.0    #在命令行mount也有提示这句,返回值为0,能正常mount。
fusermount: mount failed: Operation not permitted
echo $? ==  1    #这边多了上面那句返回,然后返回值是1,挂载失败。

WARN: volume was not unmounted cleanly.    #偶尔出现这句,可以忽略了。
.

测了几次,依然没有解决。只好再到ArchLinux的wiki上面仔细看看udev (简体中文)。按说明修改了/etc/systemd/system/systemd-udevd.service文件,也按要求把挂载动作放在 udev 规则内部,可惜测试了还是不行。也按这篇Auto-mounting USB storage with udev的示例试了一下,依旧失败返回fusermount: mount failed: Operation not permitted

KERNEL=="sd[a-z]*",ACTION=="add",RUN+="/bin/mkdir /tmp/%k",RUN+="bin/mount -r /dev/%k /tmp/%k"
.

因为udev (简体中文)写的翻译时间是2017-10-19,有点旧了,所以又仔细看了看udev英文文档。发现里面使用的示例不是bin/mount而是使用/usr/bin/systemd-mount去挂载。

ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode /media"

在控制台试了下systemd-mount命令。

[root@archlinux ~]# /usr/bin/systemd-mount /dev/sdb2 /media/sdb2
Failed to start transient mount unit: Unit media-sdb2.mount already exists.    #之前未卸载
    # echo $? == 1
[root@archlinux ~]# systemd-mount -u /media/sdb2
Stopped unit media-sdb2.mount for mount point: /media/sdb2    #卸载成功
    # echo $? == 0
[root@archlinux ~]# systemd-mount /dev/sdb2 /media/sdb2
Started unit media-sdb2.mount for mount point: /media/sdb2    #任务执行成功,不一定mount成功。
    # echo $? == 0
[root@archlinux ~]# systemctl status media-sdb2.mount
* media-sdb2.mount - /media/sdb2
   Loaded: loaded (/run/systemd/transient/media-sdb2.mount; transient)
Transient: yes
   Active: active (mounted) since Tue 2019-06-11 08:55:28 UTC; 32s ago
    Where: /media/sdb2
     What: /dev/sdb2
    Tasks: 1 (limit: 4915)
   Memory: 2.5M
   CGroup: /system.slice/media-sdb2.mount
           `-10153 /usr/bin/mount.exfat /dev/sdb2 /media/sdb2 -o rw

Jun 11 08:55:27 archlinux systemd[1]: Mounting /media/sdb2...
Jun 11 08:55:28 archlinux systemd[1]: Mounted /media/sdb2.
  # echo $? == 0

测试中发现加上--automount=yes选项之后,如果使用umount 命令去卸载,df能看出成功,但是再cd进入之前挂载的文件夹又会自动挂载起来,所以卸载动作需要使用systemd-umount 命令systemd-mount -u 命令去卸载。

最后,在.rules文件里使用systemd-mount命令试一下挂载U盘。

ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", RUN{program}+="/bin/mkdir /media/%k" ,RUN{program}+="/usr/bin/systemd-mount --no-block --collect $devnode /media/%k"

有一个U盘成功了,但有一个U盘一直没看到挂载成功,所以又用控制台试了一下。

[root@archlinux ~]# /usr/bin/systemd-mount --no-block --collect /dev/sdb2 /media/sdb2
Started unit media-sdb2.mount for mount point: /media/sdb2    #任务执行成功,不一定mount成功。
[root@archlinux ~]# systemd-mount /dev/sdb2 /media/sdb2
Job for media-sdb2.mount failed.    #不使用--no-block选项能等到结果出现
See "systemctl status media-sdb2.mount" and "journalctl -xe" for details.    #根据提示去看状态
[root@archlinux media]# systemctl status media-sdb2.mount
* media-sdb2.mount - /media/sdb2
   Loaded: loaded (/run/systemd/transient/media-sdb2.mount; transient)
Transient: yes
   Active: failed (Result: exit-code) since Tue 2019-06-11 08:48:38 UTC; 5s ago
    Where: /media/sdb2
     What: /dev/sdb2

Jun 11 08:48:38 archlinux systemd[1]: Mounting /media/sdb2...
Jun 11 08:48:38 archlinux mount[5851]: mount: /media/sdb2: unknown filesystem type 'exfat'.
Jun 11 08:48:38 archlinux systemd[1]: media-sdb2.mount: Mount process exited, code=exited, status=32/n/a
Jun 11 08:48:38 archlinux systemd[1]: media-sdb2.mount: Failed with result 'exit-code'.
Jun 11 08:48:38 archlinux systemd[1]: Failed to mount /media/sdb2.
[root@archlinux ~]# pacman -Sy exfat-utils
...     #成功安装 exfat-utils

加上--no-block可以异步等待结果,但现在并不需要,所以去掉后重试。马上返回失败信息了,然后根据提示使用systemctl status media-sdb2.mount查看状态及记录,才知道是缺少exfat支持,这个问题之前在其他设备上monut时有遇到过,使用pacman -Sy exfat-utils安装后,重新拔插U盘再试了一次:

[root@archlinux media]# systemctl status media-sdb2.mount
* media-sdb2.mount - /media/sdb2
   Loaded: loaded (/run/systemd/transient/media-sdb2.mount; transient)
Transient: yes
   Active: activating (mounting) since Tue 2019-06-11 08:50:36 UTC; 93ms ago
    Where: /media/sdb2
     What: /dev/sdb2
Cntrl PID: 7177 (mount)
    Tasks: 2 (limit: 4915)
   Memory: 2.5M
   CGroup: /system.slice/media-sdb2.mount
           |-7177 /usr/bin/mount /dev/sdb2 /media/sdb2
           `-7178 /usr/bin/mount.exfat /dev/sdb2 /media/sdb2 -o rw

Jun 11 08:50:36 archlinux systemd[1]: Mounting /media/sdb2...
    # echo $? == 3

不懂为什么返回值是3。使用df看了下,已经正常挂载了。先不理会。

.

网上随便搜了几篇文章参考,这边记录一下:

使用 udev 高效、动态地管理 Linux 设备文件
在 Linux 中如何编写基本的 udev 规则
An introduction to Udev: The Linux subsystem for managing device events
udev学习笔记汇总

关于udevadm命令,有用到几个先记录一下:

#实时监听U盘拔插,在控制台显示动态:
udevadm monitor
#模拟插拔动作:
udevadm test --action="add" /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.3/1-2.3:1.0/host3/target3:0:0/3:0:0:0/block/sdd
#规则修改后,重载生效:
udevadm control --reload

然后有几个会用到的位置也记一下:

/usr/lib/udev/rules.d    #系统定义的规则
/etc/udev/rules.d/    #自定义的规则
/usr/lib/systemd/system/systemd-udevd.service    #系统定义的配置文件
/etc/systemd/system/systemd-udevd.service    #将系统定义的配置文件复制过来修改

https://wiki.archlinux.org/index.php/Udisks_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

你可能感兴趣的:(使用udev实现插入U盘自动挂载的一些记录)