Write a bash script that executes a command when a USB device is plugged in/removed [duplicate] - linux

Is there a Bash script and/or daemon that I can write that will detect a specific USB drive and then sync that drive with a directory?

For future reference, here's how to run a bash script upon detection of a USB drive.
Connect your device and run lsusb to retrieve the device's info. You should see something similar to this:
$ lsusb
Bus 002 Device 039: ID 0bc2:2100 Seagate RSS LLC
In this case, the vendor ID of the device is 0bc2 and the product ID is 2100.
Now you can create your UDEV rule using a text editor of your choice.
$sudo vi /etc/udev/rules.d/85-my_usb_device_rule.rules
And add this:
ACTION=="add", SUBSYSTEM=="usb", SYSFS{idVendor}=="0bc2",
SYSFS{idProduct}=="2100", RUN+="/home/myhome/my_script"
/home/myhome/my_script is the path to your script which it would do whatever you want.
To make sure the detection script will execute right away, run this command to reload the UDEV rules:
$sudo udevadm control --reload-rules
This was tested on Fedora 14.

I didn't do it myself, but you can try udev rules like this:
# Hitachi SimpleDrive mini, model HTS545050B9A300 (500 GB USB HDD)
SUBSYSTEM=="block", ATTR{size}=="976768002", ATTRS{product}=="SimpleDrive mini", ATTRS{serial}=="2512009121920487", ACTION=="add", RUN+="/lib/udev/local.usb.hdd.sh add $devpath"
Place it in /etc/udev/rules.d/90-local.rules or similar place, certainly dependable on your OS.

Here is an example python deamon that you could use for the listening part, then copying the files to your directory shouldn't be a problem.

There are excellent answers here already but depending on your use case, it could be as simple as
[ -d /run/media/$USER/USB_STICK ] && do_stuff
USB_STICK here is the label of the usb stick.

Related

Auto mounting USB on a yocto linux embedded project with udev

I have a linux embedded system based on yocto up and running and need to get it to automount USB devices. The system uses udev and the following is the /etc/udev/rules.d/99-auto-mount.rules.
KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"
# Import FS infos
IMPORT{program}="/sbin/blkid -o udev -p %N"
ENV{ID_PATH}!="*-usb-*", GOTO="media_by_label_auto_mount_end"
# Get a label if present, otherwise specify one
ENV{dir_name}="USB%k"
# Global mount options
ACTION=="add", ENV{mount_options}="relatime"
# Filesystem-specific mount options
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002", ENV{DISPLAY}=":0", RUN+="/usr/local/bin/announce /media/%E{dir_name} 1"
# Mount the device
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}"
# Clean up after removal
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}", ENV{DISPLAY}=":0", RUN+="/usr/local/bin/announce /media/%E{dir_name} 0"
# Exit
LABEL="media_by_label_auto_mount_end"
It works, after a fashion, but is unable to do all I want it to do. When an USB memory stick is inserted (/dev/sda1 for the partition) it does create the folder /media/USBsda1 during add and delete the folder /media/USBsda1 during remove when the USB memory stick is yanked.
But it never mounts the USB memory stick.
I boiled the rules file down to the following bare bones file just to try and get it to mount the USB memory stick.
A USB memory stick is inserted and it's partition is then located at /dev/sda1 in the system.
KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"
# Mount the device
ACTION=="add", RUN+="/bin/mkdir -p /media/USBsda1", RUN+="/bin/mount /dev/sda1 /media/USBsda1"
# Exit
LABEL="media_by_label_auto_mount_end"
The folder gets created, but the stick is not mounted.
However, right after inserting the stick and the folder is created I can mount it manually in the console with the exact command from the rules
$> /bin/mount /dev/sda1 /media/USBsda1
and it mounts just fine?
Does anyone have any idea as to what could possibly be the problem (or more likely what is missing) or any suggestion of lines of investigations to conduct?
Yocto version = 2.1.3
udevadm version = 229
After much tinkering and reading information on the web I found a solution that worked on my system.
I had to insert a systemd service after the udev rule and then a bash script called from the service that did the heavy lifting.
So a thanks goes out to Mike Blackwell for his excellent answer to a similar question over on stackexchange. https://serverfault.com/a/767079
I used his suggestion with a few tweeks for my own system and it worked perfectly.

Creating a bash script that logs the output of 'watch lsusb' into an empty file

I have an embedded Linux system (running Ubuntu 10) on a microprocessor that has an onboard USB hub (specifically a BeagleBone Black).
I made a simple bash script that's supposed to run a command, watch lsusb; and as that runs, my program needs to dump the output my command generates into a text or JSON file (ideally on a USB stick, called usb0 for the sake of the example).
So far, this is what I have:
#!/bin/bash
#DATE=$(date +'%F %H:%M:%S')
DIR=/home/ubuntu/lsusb_logs
CMD='watch lsusb'
$CMD > $DIR
This runs until I stop it, which is fine. But when I go to look at my now created lsusb_logs file, all the data appears to be either encoded or needs to be formatted because its not at all like the original format a single lsusb or even watch lsusb outputs.
The purpose of this script is to gather historical data of the peripherals on the USB hub state over a 24 hour period in an environment chamber (climate stress testing).
Any advice or insight is helpful, thanks.
watch is going to print some non-readable characters because it needs to clear the screen every time it runs the command. You could however just run the command in an infinite while loop with some delay:
while true; do
lsusb >> lsusb_logs
sleep 1 # 1 second delay
done
Instead of looping through the same repetitive command indefinitely, you can take another approach.
You can utilize udev to monitor for plugged or unplugged USB devices, and execute a script at that time.
Example, create 2 scripts:
vi /bin/device_added.sh
vi /bin/device_removed.sh
which will log to a log file the ACTION (added or removed),
and make those executable:
chmod +x /bin/device_added.sh
chmod +x /bin/device_removed.sh
then create a udev rule that will contain the triggers on when a device change is detected:
vi /etc/udev/rules.d/80-test.rules
which will contain for example:
SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="/bin/device_added.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="/bin/device_removed.sh"
This way with your 2 scripts log only upon change, and not all the time..

Auto launch bash script that resides on USB when plugged in to system to get USB info

I am trying to figure out if there is a way to automatically run a bash script that I created and stored on a USB device, so when I plug in the USB device it automatically runs the bash script (e,g. getusbinfo.sh) and outputs the USB info to a text file (can write this text file to USB or Linux machine). I looked at a lot of solutions, and a lot of the posts seem to launch the bash script that is stored on the Linux machine rather than the USB itself which is different than what I am looking for.
Any insight would help!
It is possible to run script from connected usb pendrive. Here is the solution:
/etc/udev/rules.d/10-usb.rules:
ACTION=="add" ENV{DEVNAME}=="/dev/sd*" ENV{DEVTYPE}=="disk", RUN+="/root/sk $env{DEVNAME}"
/root/sk:
#!/bin/sh
d=$1
mount ${d}1 /mnt/usb/
/mnt/usb/getusbinfo.sh
umount ${d}1
but it assumes that it must be partition 1 mounted from this pendrive.

How to insert my driver automatically on the insertion of USB mouse in Linux System?

I know that on the insertion of any usb device in the Linux system a specific device driver got loaded. Now I want to insert my driver on the insertion of USB mouse.
I know that I can do this task using two approaches: by using depmod or using udev concept. I have read a few things about it on the Internet but I don't get the exact answer. Can anyone suggest which approach is best to use and for that in the Linux kernel tree where I need to make changes?
Thanks all for your help.
I follow the udev approach to load module automatically on the USB insertion
Below is the procedure to load your Driver automatically on the Insertion of Hot plug-gable device (I experiment with the USB mouse and below procedure is working fine for it)
Run Following command
cmd > udevadm info -a -p $(udevadm info -q path -n /dev/input/mouse)
In place of ?? in the above command user need to add the device ID based on its entry in /dev (e.g.for USB flash drive: sdb1 or sda1 etc. based on the device identity)
Get the Value of the below parameters from the output of above command
KERNEL, ATTRS{idVendor}, ATTRS{idProduct}, ATTRS{serial}
Go to /etc/dev/rule.d directory and Add your rule
cmd > sudo vim 40-usbmouse.rules
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd?1", ATTRS{idVendor}=="058f", ATTRS{idProduct}=="6387", ATTRS{serial} =="4EPLXAXE", SYMLINK+="usbpd", RUN+="/usr/local/bin/InsertModule.sh"
Save this file.
Above rule is defined for the USB Mouse.
Parameter SYMLINK creates a link of your device in the /dev directory and In RUN+ you can give your script location which is going to execute on your device insertion.
For more info on How to write a rule refer below link
http://hackaday.com/2009/09/18/how-to-write-udev-rules/
Now after you define your rule user need to restart the udev to take your rule in notice by kernel.
cmd > sudo stop udev
cmd > sudo start udev
Insert your USB and validate that your script which you define in your rule shows its effact.
For Mouse user can use below command
cmd > udevadm info -a -p $(udevadm info -q path -n /dev/input/mouse)
P.S.: cmd stands for the command shell (Terminal).The above procedure is working with any USB device.
You may use MODULE_SOFTDEP macro defined in module.h in your driver where you can specify the name of the USB driver which gets loaded when the USB mouse is inserted. This will load your driver automatically. The depmod approach is the way to go.
Use MODULE_DEVICE_TABLE macro. That will export supported device table so that your hotplug tool (whether it udev or something else) can load your module. I've described the loading process in this answer.
To see example usage, refer to drivers/hid/usbhid/usbmouse.c. If this driver compiled as module, it is loaded every time any usb mouse is attached.

bash command to force file closure on usb drive

I thought doing a sync in my bash script would force the file to be completely written out. When I looked at the thumb drive, it showed all the files I had copied, but after a power supply failure, the usb drive showed 0 files. Do I have to eject the drive manually or is there something I can do programmatically in my script?
If you want to eject the usb device from your bash script a simple umount on the device should do the trick. For example
mount /dev/usb /mnt/usb
# Your copy operations here... then on success:
umount /mnt/usb
you can also try to use the linux sync instruction that syncronize writing over disk if you're usb key is using a journalized file system

Resources