3

I created a udev rule in order to sync my USB drive with my documents folder, but it doesn't seem to be working.

95-usb-auto-sync.rules:

ACTION=="add", ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1408", RUN+="/home/riccardo/Documents/Scripts/sync-riccardo-usb.sh"

/home/riccardo/Documents/Scripts/sync-riccardo-usb.sh:

#!/bin/bash

rsync -a --delete '/home/riccardo/Documents/Development/' '/run/media/riccardo/Riccardo/Documents/Development' --exclude='*/node_modules' >> /home/riccardo/Documents/Scripts/log.txt
rsync -a --delete '/home/riccardo/Documents/KiCAD/' '/run/media/riccardo/Riccardo/Documents/KiCAD' >> /home/riccardo/Documents/Scripts/log.txt
rsync -a --delete '/home/riccardo/Documents/Personal Files/' '/run/media/riccardo/Riccardo/Documents/Personal Files' >> /home/riccardo/Documents/Scripts/log.txt
rsync -a --delete '/home/riccardo/Documents/Scripts/' '/run/media/riccardo/Riccardo/Documents/Scripts' >> /home/riccardo/Documents/Scripts/log.txt

I added the '>> /home/riccardo/Documents/Scripts/log.txt' part to check if the script was actually executed. The log.txt file remained blank though.

Toshiba USB Drive Udev info:

  looking at device '/devices/pci0000:00/0000:00:14.0/usb4/4-2':
    KERNEL=="4-2"
    SUBSYSTEM=="usb"
    DRIVER=="usb"
    ATTR{authorized}=="1"
    ATTR{avoid_reset_quirk}=="0"
    ATTR{bConfigurationValue}=="1"
    ATTR{bDeviceClass}=="00"
    ATTR{bDeviceProtocol}=="00"
    ATTR{bDeviceSubClass}=="00"
    ATTR{bMaxPacketSize0}=="9"
    ATTR{bMaxPower}=="296mA"
    ATTR{bNumConfigurations}=="1"
    ATTR{bNumInterfaces}==" 1"
    ATTR{bcdDevice}=="0001"
    ATTR{bmAttributes}=="80"
    ATTR{busnum}=="4"
    ATTR{configuration}==""
    ATTR{devnum}=="2"
    ATTR{devpath}=="2"
    ATTR{idProduct}=="1408"
    ATTR{idVendor}=="0930"
    ATTR{ltm_capable}=="no"
    ATTR{manufacturer}=="TOSHIBA"
    ATTR{maxchild}=="0"
    ATTR{product}=="USB FLASH DRIVE"
    ATTR{quirks}=="0x0"
    ATTR{removable}=="removable"
    ATTR{serial}=="C03FD5FBA9CDC1401D7FB227"
    ATTR{speed}=="5000"
    ATTR{urbnum}=="11182"
    ATTR{version}==" 3.00"

Thank you,

Riccardo

2 Answers2

6

man udev explains that the RUN+= key should not be used for long running tasks:

This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device.

Starting daemons or other long-running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.

The correct approach, for modern systems that use systemd, is SYSTEMD_WANTS. From man systemd.device:

THE UDEV DATABASE

The settings of device units may either be configured via unit files, or directly from the udev database (which is recommended). The following udev device properties are understood by systemd:


SYSTEMD_WANTS=, SYSTEMD_USER_WANTS= Adds dependencies of type Wants from the device unit to all listed units. The first form is used by the system systemd instance, the second by user systemd instances. Those settings may be used to activate arbitrary units when a specific device becomes available.

Note that this and the other tags are not taken into account unless the device is tagged with the "systemd" string in the udev database, because otherwise the device is not exposed as a systemd unit (see above).

So, your udev rule would become:

ACTION=="add", ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1408", SYSTEMD_WANTS="rsync_backup.service"

And you write a service file to call your backup script when the device is mounted:

[Unit]
Description=Backup riccardo's stuff
Requires=media-Riccardo.mount
After=media-Riccardo.mount

[Service]
ExecStart=/usr/local/bin/rsync_backup_thing

[Install]
WantedBy=media-Riccardo.mount

When /media/Riccardo is mounted, your bash script will be triggered.

jasonwryan
  • 73,126
  • Great answer! Do the 'Required' and 'After' Entries need to be modified? I replaced my systemd unit with your definition and it's not firing when I connect the device - here are the files – Riccardo Fagiolo Jul 13 '17 at 06:01
  • They just ensure that /media/Riccardo is mounted before running the script, to prevent you rsync'ing onto an unmounted target. Make sure that /media/Riccardo is actually the destination (I just used that as an example). – jasonwryan Jul 13 '17 at 06:05
  • How should I modify that if my drive is mounted in '/run/media/riccardo/Riccardo' rather that '/media/Riccardo'? – Riccardo Fagiolo Jul 13 '17 at 06:08
  • The syntax is the same: run-media-riccardo-Riccardo.mount (the slashes are changed to dashes and .mount is appended). – jasonwryan Jul 13 '17 at 06:10
  • Thank you very much. One last question: My device seems to be changing name when it is mounted. Would you happen to know a way to make it always use the same mount directory? – Riccardo Fagiolo Jul 13 '17 at 06:40
  • Label it: https://help.ubuntu.com/community/RenameUSBDrive – jasonwryan Jul 13 '17 at 06:42
  • I did, but it's being automatically mounted to 'Riccardo1'. I also noticed a Riccardo directory was created, perhaps by the systemd service? – Riccardo Fagiolo Jul 13 '17 at 06:47
  • That is an entirely separate issue (and is related to how you unmount the device). – jasonwryan Jul 13 '17 at 06:48
  • Okay i deleted the directory and now it's mounting correctly, but i'm gettin this from systemd: /usr/lib/systemd/system/usb-auto-sync.service:3: Failed to add dependency on run-media-riccardo-Riccardo – Riccardo Fagiolo Jul 13 '17 at 06:49
  • Getting this when i try to start the service manually: Failed to start usb-auto-sync.service: Unit run-media-riccardo-Riccardo.mount is masked – Riccardo Fagiolo Jul 13 '17 at 06:58
  • Failed to add dependency on run-media-riccardo-Riccardo was from before i added .mount, it's fixed now. But the service remains inactive when i plug in the drive. – Riccardo Fagiolo Jul 13 '17 at 07:15
  • getting this now: Failed to start usb-auto-sync.service: Unit run-media-riccardo-Riccardo.mount not found. – Riccardo Fagiolo Jul 13 '17 at 07:22
2

As @jasonwryan suggested I changed the udev rule to:

ACTION=="add", ATTRS{idVendor}=="0930", ATTRS{idProduct}=="1408", ENV{SYSTEMD_WANTS}="usb-auto-sync.service"

with usb-auto-sync.service:

[Unit]
Description=Auto Sync USB

[Service]
ExecStart=/home/riccardo/Documents/Scripts/sync-riccardo-usb.sh
StandardOutput=null

[Install]
WantedBy=multi-user.target
Alias=usbauto-sync.service

I enabled the service and now the script is firing.