Auto mount usb drive from udev rules and shell script

14,160

Solution 1

I think I identified the problem. Apparently, udev uses a specific namespace, indeed I can see the mount point by printing the content of /proc/<daemon_pid>/mountinfo where is the pid of the systemd-udevd service.

$ 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

So the solution should be to force udev to execute the script in root userspace. I tried the solution I found here https://unix.stackexchange.com/questions/330094/udev-rule-to-mount-disk-does-not-work

However, my system doesn't have a /usr/lib/systemd/system/systemd-udevd.service file. I created a file /etc/systemd/system/systemd-udevd.service with content

MountFlags=shared 

But with this solution, my system is not able to boot anymore.

Does someone know how I could either execute the script in root userspace or share the mount point with users?

PS : I precise I'm running a 64 bits Debian 9

Solved edit : Finally the file was located at /lib/systemd/system/systemd-udevd.service. I duplicated it in /etc/systemd/system/systemd-udevd.service and changed MountFlags=slave to MountFlags=shared and now it works perfectly :)

Solution 2

I wanted my Raspberrypi Pico microcontroller board to get automatically mounted and unmounted, much the same sort of problem as the initial question as the RPi Pico is recognized as usb storage when the bootsel button is pressed as you plug it in. So here is what I put in my /lib/udev/rules.d/10-usb-storage.rules (the exact path may be distribution dependent)

root@darkstar:/lib/udev/rules.d# cat 10-usb-storage.rules
ACTION=="add", KERNEL=="sd?[0-9]", SUBSYSTEM=="block", RUN+="usb_automount"
ACTION=="remove", KERNEL=="sd?[0-9]", SUBSYSTEM=="block", RUN+="usb_automount"
root@darkstar:/lib/udev/rules.d#

and this is the helper script called:

root@darkstar:/lib/udev/rules.d# cat /lib/udev/usb_automount
#!/bin/bash 
#this will automatically mount and umount th RPi Pico on /mnt/pico
Name=$(basename $0)
Logger="/usr/bin/logger -p local3.info -t $Name "
#logger -p local3.info -t aoutomount -- testing
Message="$* $DEVNAME $ACTION $ID_FS_LABEL"
$Logger <<< $Message

pico_add ()
{ Message="automounting  $DEVNAME $ID_FS_LABEL"
  $Logger <<< $Message
  /sbin/mount $DEVNAME /mnt/pico && $Logger <<< "mounted" || $Logger <<< "failed"
}

pico_remove ()
{ Message="umounting  $DEVNAME $ID_FS_LABEL"
  $Logger <<< $Message
  /sbin/umount -f /mnt/pico && $Logger <<< "umounted" || $LOGGER "failed"
}

case $ID_FS_LABEL in
  RPI-RP2) pico_$ACTION ;;
  *) $Logger <<< "$ID_FS_LABEL is not configured for any automatic action"
esac
root@darkstar:/lib/udev/rules.d#

To reload the udev rules: https://unix.stackexchange.com/questions/39370/how-to-reload-udev-rules-without-reboot/39371

udevadm control --reload-rules && udevadm trigger

BTW: udev seems to ignore the content of /etc/fstab

Solution 3

Could be the flie system type issue better if you specify the file system type by adding the -t FILESYSTEMTYPE argument to the command. mount -t FILESYSTEMTYPE /device_name /mount_point.

Also try to change the way you log the events, use exec command to log information no need to keep on redirecting the commands output each time. exec > $LOG_FILE 2>&1

also can you replace

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

with

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

I am not sure why the device doesn't gets mounted even though you get exit status as success. Just trying to optimize the code to catch the real issue.

Share:
14,160
Arkaik
Author by

Arkaik

Updated on June 30, 2022

Comments

  • Arkaik
    Arkaik almost 2 years

    I'm currently trying to mount any usb drive connected to my computer automaticaly. My goal is to mount usb devices either with the label if they have one or with the uuid if they don't.

    To do it I write a udev rule in /etc/udev/rules.d/10-usb-detect.rules :

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

    The script is called everytime an add event append on the block subsystem.

    The udev rule works fine however when I try to mount the file system from the script it doesn't work. What is strange is that the mount command from the script always return $?=0, so logically the file system should be mounted but it's not.

    Here is my script :

    #!/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
    

    I tried with /media/usb/test not existing and I have the expected error from the mount command. But when the folder exists he mount command returns 0 even if the filesystem is not mounted.

    Here is an output of the log file :

    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
    

    /dev/sdc1 is not mounted even if mount returns 0.

    I precise that when I mount the file system from command line, there is absolutely no problem and the file system is mounted as it should.

    Does someone has a clue about how I could debug this?

    I think the problem is because the script is called from udev because if I call it from command line it also works.