2

I'd like to have a backup script execute when certain external USB drives get mounted. I'm trying to achieve this with udev.

What I've done so far:

Identified my USB drive using sudo udevadm info --attribute-walk --name /dev/sda, the output of which is:

  looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2.3/1-5.2.3:1.0/host0/target0:0:0/0:0:0:0/block/sda':
    KERNEL=="sda"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{size}=="1953525168"
    ATTR{events_async}==""
    ATTR{ext_range}=="256"
    ATTR{range}=="16"
    ATTR{inflight}=="       0        0"
    ATTR{hidden}=="0"
    ATTR{ro}=="0"
    ATTR{discard_alignment}=="0"
    ATTR{alignment_offset}=="0"
    ATTR{capability}=="50"
    ATTR{events_poll_msecs}=="-1"
    ATTR{removable}=="0"
    ATTR{events}==""
    ATTR{stat}=="     445     7963    19565     3971        7        1       64       21        0     1036     3204        0        0        0        0"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2.3/1-5.2.3:1.0/host0/target0:0:0/0:0:0:0':
    KERNELS=="0:0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{state}=="running"
    ATTRS{inquiry}==""
    ATTRS{evt_inquiry_change_reported}=="0"
    ATTRS{evt_capacity_change_reported}=="0"
    ATTRS{device_busy}=="0"
    ATTRS{evt_mode_parameter_change_reported}=="0"
    ATTRS{evt_lun_change_reported}=="0"
    ATTRS{ioerr_cnt}=="0xc"
    ATTRS{iocounterbits}=="32"
    ATTRS{eh_timeout}=="10"
    ATTRS{vendor}=="ST310005"
    ATTRS{queue_depth}=="1"
    ATTRS{device_blocked}=="0"
    ATTRS{blacklist}==""
    ATTRS{evt_media_change}=="0"
    ATTRS{scsi_level}=="3"
    ATTRS{evt_soft_threshold_reached}=="0"
    ATTRS{iodone_cnt}=="0x1f8"
    ATTRS{queue_type}=="none"
    ATTRS{timeout}=="30"
    ATTRS{model}=="20AS            "
    ATTRS{max_sectors}=="240"
    ATTRS{iorequest_cnt}=="0x1f8"
    ATTRS{type}=="0"
    ATTRS{rev}=="    "
    ATTRS{dh_state}=="detached"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2.3/1-5.2.3:1.0/host0/target0:0:0':
    KERNELS=="target0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2.3/1-5.2.3:1.0/host0':
    KERNELS=="host0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2.3/1-5.2.3:1.0':
    KERNELS=="1-5.2.3:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb-storage"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{supports_autosuspend}=="1"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bInterfaceClass}=="08"
    ATTRS{interface}=="MSC Bulk-Only Transfer"
    ATTRS{bInterfaceProtocol}=="50"
    ATTRS{authorized}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceSubClass}=="06"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2.3':
    KERNELS=="1-5.2.3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{maxchild}=="0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{authorized}=="1"
    ATTRS{tx_lanes}=="1"
    ATTRS{manufacturer}=="Lomega"
    ATTRS{serial}=="50F26FFFFFFF"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{devpath}=="5.2.3"
    ATTRS{bmAttributes}=="c0"
    ATTRS{configuration}=="USB Mass Storage"
    ATTRS{quirks}=="0x0"
    ATTRS{ltm_capable}=="no"
    ATTRS{busnum}=="1"
    ATTRS{urbnum}=="1569"
    ATTRS{removable}=="unknown"
    ATTRS{bcdDevice}=="0000"
    ATTRS{speed}=="480"
    ATTRS{idProduct}=="0370"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{rx_lanes}=="1"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{product}=="External HD"
    ATTRS{devnum}=="19"
    ATTRS{idVendor}=="059b"
    ATTRS{version}==" 2.00"
    ATTRS{bMaxPower}=="2mA"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2':
    KERNELS=="1-5.2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{tx_lanes}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{urbnum}=="200"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{quirks}=="0x0"
    ATTRS{manufacturer}=="VIA Labs, Inc.         "
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{rx_lanes}=="1"
    ATTRS{devnum}=="6"
    ATTRS{configuration}==""
    ATTRS{bDeviceClass}=="09"
    ATTRS{busnum}=="1"
    ATTRS{version}==" 2.10"
    ATTRS{speed}=="480"
    ATTRS{idVendor}=="17ef"
    ATTRS{authorized}=="1"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{bDeviceProtocol}=="02"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{maxchild}=="4"
    ATTRS{bcdDevice}=="0a74"
    ATTRS{removable}=="unknown"
    ATTRS{devpath}=="5.2"
    ATTRS{idProduct}=="3071"
    ATTRS{product}=="USB2.0 Hub             "
    ATTRS{ltm_capable}=="no"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-5':
    KERNELS=="1-5"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{product}=="USB2.0 Hub             "
    ATTRS{devnum}=="3"
    ATTRS{rx_lanes}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bmAttributes}=="e0"
    ATTRS{devpath}=="5"
    ATTRS{speed}=="480"
    ATTRS{bDeviceClass}=="09"
    ATTRS{idProduct}=="3071"
    ATTRS{removable}=="removable"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bcdDevice}=="0a73"
    ATTRS{quirks}=="0x0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{busnum}=="1"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{configuration}==""
    ATTRS{tx_lanes}=="1"
    ATTRS{idVendor}=="17ef"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="VIA Labs, Inc.         "
    ATTRS{ltm_capable}=="no"
    ATTRS{urbnum}=="52"
    ATTRS{bDeviceProtocol}=="02"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{maxchild}=="5"
    ATTRS{version}==" 2.10"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{version}==" 2.00"
    ATTRS{tx_lanes}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{busnum}=="1"
    ATTRS{bcdDevice}=="0500"
    ATTRS{ltm_capable}=="no"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{serial}=="0000:00:14.0"
    ATTRS{configuration}==""
    ATTRS{devpath}=="0"
    ATTRS{idProduct}=="0002"
    ATTRS{devnum}=="1"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{product}=="xHCI Host Controller"
    ATTRS{speed}=="480"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{maxchild}=="12"
    ATTRS{authorized}=="1"
    ATTRS{urbnum}=="92"
    ATTRS{idVendor}=="1d6b"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{quirks}=="0x0"
    ATTRS{bDeviceClass}=="09"
    ATTRS{manufacturer}=="Linux 5.0.0-15-generic xhci-hcd"
    ATTRS{interface_authorized_default}=="1"
    ATTRS{authorized_default}=="1"
    ATTRS{rx_lanes}=="1"
    ATTRS{removable}=="unknown"

  looking at parent device '/devices/pci0000:00/0000:00:14.0':
    KERNELS=="0000:00:14.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="xhci_hcd"
    ATTRS{revision}=="0x30"
    ATTRS{d3cold_allowed}=="1"
    ATTRS{enable}=="1"
    ATTRS{ari_enabled}=="0"
    ATTRS{broken_parity_status}=="0"
    ATTRS{subsystem_device}=="0x2279"
    ATTRS{local_cpulist}=="0-7"
    ATTRS{irq}=="127"
    ATTRS{vendor}=="0x8086"
    ATTRS{msi_bus}=="1"
    ATTRS{device}=="0x9ded"
    ATTRS{dbc}=="disabled"
    ATTRS{local_cpus}=="ff"
    ATTRS{consistent_dma_mask_bits}=="64"
    ATTRS{numa_node}=="-1"
    ATTRS{dma_mask_bits}=="64"
    ATTRS{class}=="0x0c0330"
    ATTRS{subsystem_vendor}=="0x17aa"
    ATTRS{driver_override}=="(null)"

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

Based on this info, I created a file in /etc.udev/rules.d/10.autobackup.rules with:

SUBSYSTEM=="block", ACTION=="add", ATTRS{serial}=="50F26FFFFFFF", RUN+="/usr/bin/touch ~david/test_udev.txt"

After reloading the rules with sudo udevadm control --reload and running udevadm test /block/sda I get:

This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

Load module index
Parsed configuration file /usr/lib/systemd/network/99-default.link
Created link configuration context.
Reading rules file: /etc/udev/rules.d/10.autobackup.rules
Reading rules file: /usr/lib/udev/rules.d/39-usbmuxd.rules
Reading rules file: /usr/lib/udev/rules.d/40-usb_modeswitch.rules
Reading rules file: /usr/lib/udev/rules.d/40-vm-hotadd.rules
Reading rules file: /usr/lib/udev/rules.d/50-apport.rules
Reading rules file: /usr/lib/udev/rules.d/50-firmware.rules
Reading rules file: /usr/lib/udev/rules.d/50-udev-default.rules
Reading rules file: /usr/lib/udev/rules.d/55-dm.rules
Reading rules file: /usr/lib/udev/rules.d/55-ippusbxd.rules
Reading rules file: /usr/lib/udev/rules.d/56-hpmud.rules
Reading rules file: /usr/lib/udev/rules.d/60-block.rules
Reading rules file: /usr/lib/udev/rules.d/60-cdrom_id.rules
Reading rules file: /usr/lib/udev/rules.d/60-crda.rules
Reading rules file: /usr/lib/udev/rules.d/60-drm.rules
Reading rules file: /usr/lib/udev/rules.d/60-evdev.rules
Reading rules file: /usr/lib/udev/rules.d/60-input-id.rules
Reading rules file: /usr/lib/udev/rules.d/60-inputattach.rules
Reading rules file: /usr/lib/udev/rules.d/60-libfprint0.rules
Reading rules file: /usr/lib/udev/rules.d/60-libgphoto2-6.rules
Reading rules file: /usr/lib/udev/rules.d/60-libsane.rules
Reading rules file: /usr/lib/udev/rules.d/60-pcmcia.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-alsa.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-input.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-storage-dm.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-storage-tape.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-storage.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-v4l.rules
Reading rules file: /usr/lib/udev/rules.d/60-sensor.rules
Reading rules file: /usr/lib/udev/rules.d/60-serial.rules
Reading rules file: /usr/lib/udev/rules.d/61-gdm.rules
Reading rules file: /usr/lib/udev/rules.d/61-gnome-settings-daemon-rfkill.rules
Reading rules file: /usr/lib/udev/rules.d/61-persistent-storage-android.rules
Reading rules file: /usr/lib/udev/rules.d/64-btrfs.rules
Reading rules file: /usr/lib/udev/rules.d/64-xorg-xkb.rules
Reading rules file: /usr/lib/udev/rules.d/65-libwacom.rules
Reading rules file: /usr/lib/udev/rules.d/66-snapd-autoimport.rules
Reading rules file: /usr/lib/udev/rules.d/69-cd-sensors.rules
Reading rules file: /usr/lib/udev/rules.d/69-libmtp.rules
Reading rules file: /usr/lib/udev/rules.d/69-wacom.rules
Reading rules file: /usr/lib/udev/rules.d/70-joystick.rules
Reading rules file: /usr/lib/udev/rules.d/70-mouse.rules
Reading rules file: /usr/lib/udev/rules.d/70-power-switch.rules
Reading rules file: /usr/lib/udev/rules.d/70-printers.rules
Reading rules file: /etc/udev/rules.d/70-snap.core.rules
Reading rules file: /usr/lib/udev/rules.d/70-spice-vdagentd.rules
Reading rules file: /usr/lib/udev/rules.d/70-touchpad.rules
Reading rules file: /usr/lib/udev/rules.d/70-u2f.rules
Reading rules file: /usr/lib/udev/rules.d/70-uaccess.rules
Reading rules file: /usr/lib/udev/rules.d/71-power-switch-proliant.rules
Reading rules file: /usr/lib/udev/rules.d/71-seat.rules
Reading rules file: /usr/lib/udev/rules.d/71-u-d-c-gpu-detection.rules
Reading rules file: /usr/lib/udev/rules.d/73-seat-late.rules
Reading rules file: /usr/lib/udev/rules.d/73-special-net-names.rules
Reading rules file: /usr/lib/udev/rules.d/73-usb-net-by-mac.rules
Reading rules file: /usr/lib/udev/rules.d/75-net-description.rules
Reading rules file: /usr/lib/udev/rules.d/75-probe_mtd.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-cinterion-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-dell-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-ericsson-mbm.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-fibocom-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-haier-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-huawei-net-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-longcheer-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-mtk-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-nokia-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-pcmcia-device-blacklist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-qdl-device-blacklist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-sierra.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-simtech-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-telit-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-ublox-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-usb-device-blacklist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-usb-serial-adapters-greylist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-x22x-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-zte-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/78-graphics-card.rules
Reading rules file: /usr/lib/udev/rules.d/78-sound-card.rules
Reading rules file: /usr/lib/udev/rules.d/80-debian-compat.rules
Reading rules file: /usr/lib/udev/rules.d/80-drivers.rules
Reading rules file: /usr/lib/udev/rules.d/80-ifupdown.rules
Reading rules file: /usr/lib/udev/rules.d/80-iio-sensor-proxy.rules
Reading rules file: /usr/lib/udev/rules.d/80-libinput-device-groups.rules
Reading rules file: /usr/lib/udev/rules.d/80-mm-candidate.rules
Reading rules file: /usr/lib/udev/rules.d/80-net-setup-link.rules
Reading rules file: /usr/lib/udev/rules.d/80-udisks2.rules
Reading rules file: /usr/lib/udev/rules.d/84-nm-drivers.rules
Reading rules file: /usr/lib/udev/rules.d/85-brltty.rules
Reading rules file: /usr/lib/udev/rules.d/85-hdparm.rules
Reading rules file: /usr/lib/udev/rules.d/85-hplj10xx.rules
Reading rules file: /usr/lib/udev/rules.d/85-nm-unmanaged.rules
Reading rules file: /usr/lib/udev/rules.d/85-regulatory.rules
Reading rules file: /usr/lib/udev/rules.d/89-alsa-ucm.rules
Reading rules file: /usr/lib/udev/rules.d/90-alsa-restore.rules
Reading rules file: /usr/lib/udev/rules.d/90-bolt.rules
Reading rules file: /usr/lib/udev/rules.d/90-console-setup.rules
Reading rules file: /usr/lib/udev/rules.d/90-fwupd-devices.rules
Reading rules file: /usr/lib/udev/rules.d/90-libinput-model-quirks.rules
Reading rules file: /usr/lib/udev/rules.d/90-nm-thunderbolt.rules
Reading rules file: /usr/lib/udev/rules.d/90-pulseaudio.rules
Reading rules file: /usr/lib/udev/rules.d/95-cd-devices.rules
Reading rules file: /usr/lib/udev/rules.d/95-dm-notify.rules
Reading rules file: /usr/lib/udev/rules.d/95-upower-csr.rules
Reading rules file: /usr/lib/udev/rules.d/95-upower-hid.rules
Reading rules file: /usr/lib/udev/rules.d/95-upower-wup.rules
Reading rules file: /usr/lib/udev/rules.d/97-hid2hci.rules
Reading rules file: /usr/lib/udev/rules.d/99-systemd.rules
Rules contain 393216 bytes tokens (32768 * 12 bytes), 38404 bytes strings
31877 strings (265263 bytes), 28376 de-duplicated (230361 bytes), 3502 trie nodes used
Invalid inotify descriptor.
Starting 'ata_id --export /dev/sda'
Process 'ata_id --export /dev/sda' failed with exit code 1.
sda: Failed to create symlink '/dev/disk/by-id/usb-ST310005_20AS_50F26FFFFFFF-0:0.tmp-b8:0' to '../../sda': Permission denied
DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2.3/1-5.2.3:1.0/host0/target0:0:0/0:0:0:0/block/sda
DEVNAME=/dev/sda
DEVTYPE=disk
MAJOR=8
MINOR=0
ACTION=add
SUBSYSTEM=block
ID_VENDOR=ST310005
ID_VENDOR_ENC=ST310005
ID_VENDOR_ID=059b
ID_MODEL=20AS
ID_MODEL_ENC=20AS\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
ID_MODEL_ID=0370
ID_REVISION=0000
ID_SERIAL=ST310005_20AS_50F26FFFFFFF-0:0
ID_SERIAL_SHORT=50F26FFFFFFF
ID_TYPE=disk
ID_INSTANCE=0:0
ID_BUS=usb
ID_USB_INTERFACES=:080650:
ID_USB_INTERFACE_NUM=00
ID_USB_DRIVER=usb-storage
DEVLINKS=/dev/disk/by-path/pci-0000:00:14.0-usb-0:5.2.3:1.0-scsi-0:0:0:0 /dev/disk/by-id/usb-ST310005_20AS_50F26FFFFFFF-0:0
ID_PATH=pci-0000:00:14.0-usb-0:5.2.3:1.0-scsi-0:0:0:0
ID_PATH_TAG=pci-0000_00_14_0-usb-0_5_2_3_1_0-scsi-0_0_0_0
TAGS=:systemd:
USEC_INITIALIZED=3351039864
run: '/usr/bin/unshare -m /usr/bin/snap auto-import --mount=/dev/sda'
run: '/usr/bin/touch ~david/test_udev.txt'
run: '/lib/udev/hdparm'
Unload module index
Unloaded link configuration context.

Which appears to indicate that the touch command in my script should be executed when the USB drive gets added (and after mounting the drive, which is a constraint I will need when performing the backup). Yet, next time I add the drive (turning it off then on), no file gets created at ~david/test_udev.txt.

Executing sudo udevadm trigger doesn't get the file to be created either.

The end goal is for a backup command to execute, but at this time I'm just trying to touch a file to get the basics working...

  • udevadm trigger by default does a change action. Your rule is add. Use udevadm monitor to show what happens when you turn the HDD on and off. You also should use a wrapper script for doing things: https://askubuntu.com/questions/25071/how-to-run-a-script-when-a-specific-flash-drive-is-mounted – Thomas May 19 '19 at 14:14
  • Is this ~david/test_udev.txt a typo! – George Udosen May 19 '19 at 14:55
  • Does ~David exist? – George Udosen May 19 '19 at 15:05
  • @Thomas I initially tried with a wrapper script since that's the way the actual backup job will be triggered. When debugging the issue, I resorted to a direct command to be able to reduce the scope of potential problems (file permissions on the script file, etc.). Looking at the linked answer, I'm currently attempting to use systemd to achieve my goal, but I'm missing a final piece: https://askubuntu.com/questions/1144587/systemd-user-service-not-starting-on-login – David Sulc May 19 '19 at 19:33
  • @GeorgeUdosen ~david exists. I'm not sure why you're asking if the filename is a typo: it isn't, but do you think it might be causing issues? Note that I've also tried to use systemd to trigger the backup: https://askubuntu.com/questions/1144587/systemd-user-service-not-starting-on-login – David Sulc May 19 '19 at 19:35
  • @davidsulc ~David should be ~/David! So you shouldn't expect that backup to occur if the location doesn't exist! – George Udosen May 19 '19 at 19:39
  • Nope, the folder I want is /home/david which has ~david as a shorthand. ~/david would resolve to /home/joe/david (assuming the current user is joe). – David Sulc May 20 '19 at 17:02

1 Answers1

1

Edit: it turns out my specific case/problems were related to my encrypted home dir and using only systemd was all that was needed for it to work, although the unit has to be started on each login. For more info see here.


Looking into this more, it appears that triggering the backup script (which could be "long running" for some definition of "long") isn't the best approach anyway (it could delay other udev stuff). Instead, it's better to have udev "want" a systemd user unit that will then trigger the actual backup script. Here's what I did:

Label the drives in GParted (e.g. to be called "backup") so they will always be mounted at the same mountpoint.

Add a user systemd unit in ~/.config/systemd/user/auto-usb-backup.service with:

[Unit]
Description=Autobackup to USB drive

[Service]
ExecStart=/home/david/Documents/computer/backup/scripts/backup_to_usb.sh

Reload the daemon: systemctl --user daemon-reload so it's aware of the new unit.

Then, add a udev rule to trigger the unit when a USB drive with a "backup" partition is mounted. Create a udev rule at /etc/udev/rules.d/90-auto-usb-backup.rules containing

SUBSYSTEM=="block", ACTION=="add", ENV{ID_FS_LABEL}=="backup", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}="auto-usb-backup.service"

The ID_FS_LABEL parameter name and value were obtained using udevadm monitor --environment --udev and plugging in the drive, but the lsusb (and its -v option) and udevadm info -a -p $(udevadm info -q path -n /dev/sda) may also be useful to fine-tune rules (e.g. have the udev rule trigger only for a specific drive based on its serial number).

Reload udev for the new rule to apply: sudo udevadm control --reload

Check the rule will trigger for the drive with udevadm test /block/sda (where sda is the current drive mountpoint): you should see TAGS=:systemd: among the output.

Finally, turn remove and add the drive: the script in the systemd user unit defined above should get executed. You can double-check this (and debug) using journalctl --user-unit auto-usb-backup -r -b (note that on some systems the --user-unit option may be -u instead).

Note: it appears the script gets triggered before the drive is done mounting, so the backup script called by the systemd unit has a wait loop to sleep until the folders its looking for are available.

Resources that were helpful:

https://vic.demuzere.be/articles/using-systemd-user-units/

https://borgbackup.readthedocs.io/en/stable/deployment/automated-local.html