2019-06-10 遇到的一点小问题
新需求是在U盘插入设备时实现自动挂载功能,一般都是推荐使用udev。记录一下第一次使用出现的问题。
.
刚开始先按网上找的方法
,在/etc/udev/rules.d/
创建个.rules文件,再根据插入动作调用.sh文件来执行mount操作:
KERNEL=="sd[a-z]*",ACTION=="add",RUN+="/srv/wannoo.sh %k"
语法挺简单的,就是容易遇坑:有一次KERNEL和ACTION顺序弄反,然后就执行失败;还有一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)