7

I've made a little udev rule that launch a script that make an archive of my ~/Documents directory. That do the job, but when I read the log file, it seems that the archive script is executed 3 times when I plug my key.

Here's my rule:

ACTION=="add", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1642", RUN+="/bin/sh /root/auto-archive" 

Here's my script:

#! /bin/sh

sleep 5

# test if awesome is running
if ps aux | grep -v launch | grep -v grep | grep awesome
then
    echo awesome is running >> /home/purplepsycho/log
else
    # echo awesome not running another guy must be logged
    exit
fi

if mount | grep /media/usb
then
    echo /media/usb already mounted >> /home/purplepsycho/log
    exit
fi

# mount key
echo mounting... >> /home/purplepsycho/log
/usr/bin/sudo -u purplepsycho mount /media/usb

# test if mount have been succesful
if [ $? -ne 0 ]
then
    echo mount failed >> /home/purplepsycho/log
    exit
fi
# archive dir
ARC_DIR="/media/usb/archive"

# make directory
mkdir -p $ARC_DIR

# archive name
NAME=$(date +"archive-%Y-%m-%d.tgz")

# test if an archive already exists for today
if [ -f $ARC_DIR/$NAME ] 
then
    echo archive file already exists for today >> /home/purplepsycho/log
    exit
fi

# initialize log file
echo $NAME > $ARC_DIR/files.txt

# make the archive
tar -zcvf $ARC_DIR/$NAME /home/purplepsycho/Documents/* >> $ARC_DIR/files.txt

Any idea? Thanks.

---Edit after Sparhawk comment---

I run udevadm on my key:

udevadm info -a -p $(udevadm info -q path -n /dev/sbd)

Which gave:

looking at device '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host4/target4:0:0/4:0:0:0/block/sdb':
  KERNEL=="sdb"
  SUBSYSTEM=="block"
  DRIVER==""

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host4/target4:0:0/4:0:0:0':
  KERNELS=="4:0:0:0"
  SUBSYSTEMS=="scsi"
  DRIVERS=="sd"

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host4/target4:0:0':
  KERNELS=="target4:0:0"
  SUBSYSTEMS=="scsi"
  DRIVERS==""

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host4':
  KERNELS=="host4"
  SUBSYSTEMS=="scsi"
  DRIVERS==""

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0':
  KERNELS=="1-1:1.0"
  SUBSYSTEMS=="usb"
  DRIVERS=="usb-storage"

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-1':
  KERNELS=="1-1"
  SUBSYSTEMS=="usb"
  DRIVERS=="usb"
  ATTRS{idVendor}=="0951"
  ATTRS{idProduct}=="1642"

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1':
  KERNELS=="usb1"
  SUBSYSTEMS=="usb"
  DRIVERS=="usb"
  ATTRS{idVendor}=="1d6b"
  ATTRS{idProduct}=="0002"

looking at parent device '/devices/pci0000:00/0000:00:1d.7':
  KERNELS=="0000:00:1d.7"
  SUBSYSTEMS=="pci"
  DRIVERS=="ehci-pci"
  ATTRS{irq}=="23"

looking at parent device '/devices/pci0000:00':
  KERNELS=="pci0000:00"
  SUBSYSTEMS==""
  DRIVERS==""

I tried to write rules only based on:

  KERNELS=="1-1"
  SUBSYSTEMS=="usb"
  DRIVERS=="usb"
  ATTRS{idVendor}=="0951"
  ATTRS{idProduct}=="1642"

and

  KERNELS=="usb1"
  SUBSYSTEMS=="usb"
  DRIVERS=="usb"
  ATTRS{idVendor}=="1d6b"
  ATTRS{idProduct}=="0002"

The result is the same: script is called multiple times...

Mathieu
  • 2,719
  • 2
    I don't have time to write up a full answer, but it may be that it's triggering on the most "parent" device. i.e. the enclosure. It then triggers on the physical hard drive (as a subset of the enclosure) and the volume (as a subset of the hard drive, which is a subset of the enclosure). Try finding the idProduct of the smallest unit (i.e. the volume). – Sparhawk Dec 15 '15 at 21:21

2 Answers2

8

The problem comes from your rule: you only try to match a parent of your device, and not the device itself... see http://reactivated.net/writing_udev_rules.html#sysfstree for details:

  • you must match the device (KERNEL=, SUBSYSTEM=, ATTR= ...),
  • and one of its parent (KERNELS=, SUBSYSTEMS=, ATTRS= ...) (note the 'S' at the end on fields).

The corrected rule is:

ACTION=="add", KERNEL=="sdb1", SUBSYSTEM=="block", ATTRS{vendor}=="Kingston", ATTRS{model}=="DT 101 G2", RUN+="/bin/sh /root/auto-archive"
Mathieu
  • 2,719
1

I'm just adding my (empirical) findings here : in case it helps others.

I am writing a script to run when a Clip Jam is plugged into the USB Port of a Raspberry Pi 4. (Running Rasbian Buster, late 2021 release) : this is essentially a USB storage device - and gets mounted as a filesystem.

/dev/sda1       7.8G  7.6G  206M  98% /media/pi/Clip Jam

I was also seeing my script being run multiple times (like 25 times!) when I plugged in the device.

The post above really helped notice the difference between the singular ("Kernel") and plural entries ("Kernels") in the output of the command:

udevadm info -a /dev/sda1

But what I didn't appreciate - was what the rules appears to be matching on. It seems that you need to match info which appears exactly once in the parent list.

In my case; I was able to identify a parent which uniquely had this entry in it:

ATTRS{product}=="Clip Jam"

So the rule (/etc/udev/rules.d/999-tester.rules) I wrote which works for me was this:

ACTION=="add" \
, KERNEL=="sda1" \
, SUBSYSTEM=="block" \
, ATTRS{product}=="Clip Jam" \
, ENV{DISPLAY}=":0" \
, ENV{XAUTHORITY}="/home/pi/.Xauthority" \
, RUN+="/home/pi/Desktop/tester.sh"

And here it is annotated :

ACTION=="add" \ <-- The action we are interested in.
, KERNEL=="sda1" \ <---- Top of the output of the 'udevadm' command.
, SUBSYSTEM=="block" \ <---- Top of the output of the 'udevadm' command.
, ATTRS{product}=="Clip Jam" \ <--- Found (trial and error) in list of parents; unique entry throughout 'udevadm' output.
, ENV{DISPLAY}=":0" \ <-- Taken from 'env' output
, ENV{XAUTHORITY}="/home/pi/.Xauthority" \ <-- Taken from 'env' output
, RUN+="/home/pi/Desktop/tester.sh" <-- Testing script only.

One other to remember: re-run the refresh command after editing the rule command! (Easy to forget!)

sudo udevadm control --reload