Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 3555

Raspberry Pi OS • Re: How to read contents of flash drive when it's plugged in

$
0
0
I ended up using a systemd service. The udev script remains like this

Code:

ACTION=="add",    SUBSYSTEM=="usb", RUN="/opt/udev-connect.sh"ACTION=="remove", SUBSYSTEM=="usb", RUN="/opt/udev-disconnect.sh"
And the actual scripts look like this

Code:

#!/bin/bash# udev-connect.shecho "Device connected. Starting service-port.service"systemctl start service-port.service

Code:

#!/bin/bash# udev-disconnect.shecho "Device disconnected. Stopping service-port.service"systemctl stop service-port.service
As you can see, the udev scripts are performing extremely minimal work, just starting and stopping a service. The service file looks like this

Code:

[Unit]Description=Service port flash drive handler[Service]Type=oneshotExecStart=/opt/connect-service-port-drive.shExecStopPost=/opt/disconnect-service-port-drive.shRemainAfterExit=yesRestart=no[Install]WantedBy=multi-user.target

Because of Type=oneshot and RemainAfterExit=yes, this service will simply run its ExecStart script when started and run its ExecStopPost script when stopped. While it's running, it's doing nothing, but that's ok.

Finally, the actual scripts connect-service-port-drive.sh and disconnect-service-port-drive.sh can contain the actual code that I want to run when the USB device is attached or removed.

Here is part of my connect script that mounts the drive and reads from it:

Code:

#!/bin/bashecho "USB drive connected"echo "Mounting device..."# the /dev/sd# device will not be available right away, so we need to keep# trying to find it until it's actually found. It usually takes about 4 or 5# tries, but here we use a maximum of 100 triesMOUNTED=0TRIES=0while [ $TRIES -le 100 ] && [ $MOUNTED -ne 1 ]; do    echo "    ...attempt number $TRIES"    TRIES=$(($TRIES + 1))    # list block devices    #   * --output specifies which data to print    #   * --paths means show the full paths of the devices    #   * --json puts the output into JSON format    #   * | jq passes the output to the jq JSON parser    #   * -r causes jq to output a raw string (without quotes)    #   * '.blockdevices[] | select(.rm == true) | .children[0] | .name')    #         finds all the block devices that are removable and gets the first    #         child of each and selects the name attribute from the output.    # The final result should be either an empty string or the name of the    # device. However, I found that sometimes it was null    DEVICE_NAME=$(lsblk --output NAME,MOUNTPOINTS,RM --paths --json | jq -r '.blockdevices[] | select(.rm == true) | .children[0] | .name')    # if the device name is empty or null then just sleep a little and try    # again    if [ -z $DEVICE_NAME ] || [ $DEVICE_NAME == "null" ]; then        sleep 0.1s    else        # if we found the device, then we need to unmount any previously        # mounted devices. If there are multiple devices mounted at the        # location, the umount command will unmount one at a time. If there are        # no devices mounted, then the umount command will return a non-zero        # exit status. So here we just keep calling umount until we get an        # error (capped at 100 tries to prevent an infinite loop)        NEED_TO_UNMOUNT=1        UMOUNT_TRIES=0        while [ $NEED_TO_UNMOUNT == 1 ] && [ $UMOUNT_TRIES -le 100 ]; do            UMOUNT_TRIES=$(($UMOUNT_TRIES + 1))            umount /media/service_port            if [ $? != 0 ]; then                NEED_TO_UNMOUNT=0            fi        done        # mount the new device        mount $DEVICE_NAME /media/service_port        MOUNTED=1    fidoneif [ $MOUNTED == 1 ]; then    echo "Device mounted"else    echo "Failed to mount device"    exit 1fi# do actual work here and be able to read from /media/service_portecho "Done"

Statistics: Posted by nullromo — Wed Jun 11, 2025 6:24 pm



Viewing all articles
Browse latest Browse all 3555

Trending Articles