In the project Raspberry Pi my latest, I don’t want to use the network to automatically get data off my Raspberry. The solution to this problem is to run a Python script when the USB is plugged into the Raspberry.
Join the channel Telegram of the AnonyViet 👉 Link 👈 |
Rules of USB
The simplest part is providing a set of rules about what to do when you plug in a storage device. These include a script when we plug in the USB and a script when we unplug it:
ACTION=="add", SUBSYSTEM=="usb", PROGRAM="<full_path_here>/on_usb_in.sh" ACTION=="remove", SUBSYSTEM=="usb", PROGRAM="<full_path_here>/on_usb_out.sh"
These two lines must be in the directory etc/udev/rules.d
. Eg:
nano /etc/udev/rules.d/custom_usb.rules
When disconnecting the USB
We can use the LOCK file to show only when the device is plugged in and not run multiple instances of the code. This method will have disadvantages when we plan to plug in multiple USBs at the same time, but this is less likely to cause problems in normal use.
Since our “connect” file will generate the key, the disconnect script needs to remove this. Thus, the contents of the script .../on_usb_out.sh
Ours are:
#!/bin/sh LOCK=/tmp/lockfile_for_plug_usb/bin/ rm -f /tmp/lockfile_for_plug_usb
When connecting USB
When we realize a new serial bus, we need to create a file LOCK. Once that’s done, we can run any script we want.
Scripts .../on_usb_in.sh
store the current date in a log file and then run a Python script to determine if there is a data storage device. If it does, it will pass data to it:
#!/bin/sh LOCK=/tmp/lockfile_for_plug_usb if [ -f $LOCK ]then exit 1 else touch $LOCK; # tlệnh thực tế để chạy khi cắm USB /bin/date >> /root/usb.log; /usr/bin/python3 /root/transfer.py >> /root/usb.log; fi
Python script
Theoretically, the body of a Python script can do anything. In my case, I started by delaying (waiting) a small amount for the USB to fully attach:
import os, time, re time.sleep(10) #
Extract drive information
Next, I will extract information about all connected USB drives using the command blkid
:
devices = os.popen('sudo blkid').readlines()
From here, I can extract each entry into a list of dictionary objects containing all the relevant information. Since I don’t care about the Raspberry Pi SD card, I just select the items that are in /dev/sd**
and has the format sd[a-z][1-9]
(For example: sda1
):
usbs = [] for u in devices: loc = [u.split(':')[0]] if '/dev/sd' not in loc[0]: continue # skip loc+=re.findall(r'"[^"]+"',u) columns = ['loc']+re.findall(r'\b(\w+)=',u) usbs.append(dict(zip(columns,loc)))
View selected devices
Now that we have a list of USBs, we can print their locations, unique identifiers, and label names:
for u in usbs: print ('Device %(LABEL)s is located at $(loc)s with UUID of $(UUID)s'%u )
Such a function can help filter out specific devices by their UUID and perform tasks only for those devices that we have pre-approved.
Mount
Finally, we can mount USB devices if we want to transfer data to them.
os.system('sudo mount $(loc)s /myusb'%u)
The command below will copy data to your usb:
cp ./file2backup /myusb
Unmount
Once done, we need to disconnect the usb before unplugging it. Similarly, this is done using:
os.system('sudo umount /myusb')
Make scripts executable
The last thing you might need to do is execute all the files with chmod a + x and possibly reboot the system for the changes to take effect.
Conclusion
We have created a rule that enforces when plugging and unplugging the USB. In this article, we used a LOCK file to stop multiple executions and run a Python script to determine the devices plugged in. If a device matches our criteria, then we mount it and do what we want – all automatically.
In the case of the Raspberry Pi, this allows us to effectively offload all the data and without the need for a network or cellular signal. The biggest advantage of this approach (besides its simplicity) is that for difficult environments, data transfer is possible through the use of a single connection port.