udev自动挂载U盘

April 10, 2014

以前用udev规则自动挂载U盘是很简单的,直接在规则里匹配然后执行mkidrmount就搞定了。不过systemd在212版之后,systemd-udevd守护进程回在另一个命名空间里运行,在里面进行的mount是“没效”的,change log:

        * systemd-udevd will now run in a disassociated mount
          namespace. To mount directories from udev rules make sure to
          pull in mount units via SYSTEMD_WANTS properties.

看来要写个systemd service,然后在udev规则里用SYSTEMD_WANTS来执行。这就好办了,在udev规则里启动systemd service时,我们通过%I来传递设备路径,然后在systemd service再用一个脚本重新获得其他必要的信息然后挂载。

上面是正解,下面我的折腾,因为udev规则里已经有了文件系统类型、UUID这些信息,我不想再去获取,所以直接构造一个命令,通过%I传过去。

首先是udev规则:

KERNEL!="sd[b-z]?", GOTO="automount_exit"
ACTION!="add", GOTO="automount_exit"

ENV{ID_FS_TYPE}=="ext4",      ENV{MOUNT_OPTS}="defaults,delalloc,nodiratime,noatime,commit=300"
ENV{ID_FS_TYPE}=="ext2|ext3", ENV{MOUNT_OPTS}="defaults,nodiratime,noatime,commit=350"
ENV{ID_FS_TYPE}=="vfat",      ENV{MOUNT_OPTS}="defaults,utf8"

ACTION=="add", SUBSYSTEM=="block", \
    RUN+="/usr/bin/mkdir -p /tmp/mnt/%E{ID_PART_TABLE_UUID}", \
    ENV{SYSTEMD_WANTS}+="automount@%E{MOUNT_OPTS}\x20$root/%k\x20\x2d\x2d\x20/tmp/mnt/%E{ID_PART_TABLE_UUID}.service"

LABEL="automount_exit"

automount@和.service之间就是我传递的参数。

然后是服务(automount@.service):

[Unit]
Description=Automount(Damn Systemd and Udev)

[Service]
Type=oneshot
ExecStart=/bin/sh -c "exec mount -o %I"

sh -c好像挺危险的,所以我只用了uuid构造命令。

纯折腾啊。