首页 文章

从udev规则和shell脚本自动挂载USB驱动器

提问于
浏览
2

我正在尝试自动安装连接到我的电脑的任何USB驱动器 . 我的目标是使用标签安装usb设备(如果有的话),如果没有,则使用uuid .

为此,我在/etc/udev/rules.d/10-usb-detect.rules中写了一个udev规则:

ACTION=="add", KERNEL=="sd?[0-9]", SUBSYSTEM=="block", RUN+="/usr/local/bin/add.sh"

每次在块子系统上追加添加事件时,都会调用该脚本 .

udev规则工作正常,但是当我尝试从脚本安装文件系统时,它不起作用 . 奇怪的是脚本中的mount命令总是返回$?= 0,所以逻辑上应该挂载文件系统,但事实并非如此 .

这是我的脚本:

#!/bin/bash

LOG_FILE=<path_to_file>

echo "New usb device detected at $DEVNAME" >> $LOG_FILE

echo "mount $DEVNAME /media/usb/test" >> $LOG_FILE

mount $DEVNAME /media/usb/test &>> $LOG_FILE

ret=$?
echo "$ret" >> $LOG_FILE

if [ $ret == "0" ]; then
    echo "$DEVNAME mounted at /media/usb/test"  >> $LOG_FILE
else
    echo "Failed to mount $DEVNAME at /media/usb/test"  >> $LOG_FILE
fi

echo "" >> $LOG_FILE

我试过/ media / usb / test不存在,我从mount命令得到了预期的错误 . 但是当文件夹存在时,即使未安装文件系统,mount命令也会返回0 .

这是日志文件的输出:

New usb device detected at /dev/sdc1
mount /dev/sdc1 /media/usb/test
mount: mount point /media/usb/test does not exist
32
Failed to mount /dev/sdc1 at /media/usb/test

New usb device detected at /dev/sdc1
mount /dev/sdc1 /media/usb/test
0
/dev/sdc1 mounted at /media/usb/test

即使mount返回0,也不会挂载/ dev / sdc1 .

我确切地说,当我从命令行挂载文件系统时,绝对没有问题,文件系统按原样安装 .

有人知道如何调试这个吗?

我认为问题是因为脚本是从udev调用的,因为如果我从命令行调用它也可以 .

2 回答

  • 1

    我想我发现了这个问题 . 显然,udev使用特定的命名空间,实际上我可以通过打印 /proc/<daemon_pid>/mountinfo 的内容来查看挂载点,其中是systemd-udevd服务的pid .

    $ cat /proc/240/mountinfo
    [...]
    228 43 8:17 / /media/usb/test rw,relatime - vfat /dev/sdb1 rw,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro
    
    $ df
    Sys. de fichiers blocs de 1K  Utilisé Disponible Uti% Monté sur
    udev                 1975740        0    1975740   0% /dev
    tmpfs                 397376     5916     391460   2% /run
    /dev/sda2           75733088 69473400    2389532  97% /
    tmpfs                1986868   111860    1875008   6% /dev/shm
    tmpfs                   5120        4       5116   1% /run/lock
    tmpfs                1986868        0    1986868   0% /sys/fs/cgroup
    tmpfs                 397372       28     397344   1% /run/user/112
    tmpfs                 397372       24     397348   1% /run/user/1001
    

    所以解决方案应该是强制udev在root用户空间中执行脚本 . 我试过我在这里找到的解决方案https://unix.stackexchange.com/questions/330094/udev-rule-to-mount-disk-does-not-work

    但是,我的系统没有 /usr/lib/systemd/system/systemd-udevd.service 文件 . 我创建了一个包含内容的文件 /etc/systemd/system/systemd-udevd.service

    MountFlags=shared
    

    但是使用这个解决方案,我的系统无法再启动了 .

    有人知道如何在root用户空间中执行脚本或与用户共享挂载点吗?

    PS:我确切地说我正在运行64位Debian 9

    Solved edit : 最后,该文件位于 /lib/systemd/system/systemd-udevd.service . 我在 /etc/systemd/system/systemd-udevd.service 重复了它,并将 MountFlags=slave 更改为 MountFlags=shared ,现在它完美地工作了:)

  • 3

    如果通过向命令添加-t FILESYSTEMTYPE参数来指定文件系统类型,则可能更好地解决了系统类型问题 . mount -t FILESYSTEMTYPE /device_name /mount_point .

    还尝试更改记录事件的方式,使用exec命令记录信息,无需每次都重定向输出的命令 . exec > $LOG_FILE 2>&1

    也可以替换

    mount $DEVNAME /media/usb/test &>> $LOG_FILE
    ret=$?
    echo "$ret" >> $LOG_FILE
    if [ $ret == "0" ]; then
    echo "$DEVNAME mounted at /media/usb/test"  >> $LOG_FILE
    else
    echo "Failed to mount $DEVNAME at /media/usb/test"  >> $LOG_FILE
    fi
    

    mount -t vfat $DEVNAME /media/usb/test
    if [ $? -eq 0 ]; then
    echo " $DEVNAME Mounted"
    else
    echo " $DEVNAME not Mounted"
    fi
    

    我不确定为什么即使您获得退出状态成功,设备也不会被挂载 . 只是尝试优化代码以捕捉真正的问题 .

相关问题