I wanted to be able to automatically copy the contents of the SD Card from my camera onto my NAS when plugged in. The best way to go about this is to utilize udev rules to trigger an action when it detects that specific SD card.

There are a few direct issues with this process:

  1. udev rules on (most) systems run in a special mode that prevents them from using the mount command
  2. things get really funky when there's any kind of latency with the script that is running.

This made getting this working slightly tricky because neither of these things were really obvious and most examples floating around were just specifically around mounting the disk, not preforming an action against it.

I created this simple bash script to setup the mounts, rsync the files and unmount the sdcard as well as sent a notification once it completes.

I created this in /usr/local/bin/lumix.sh you would obviously need to customize this a bit to fit your setup.

#!/bin/bash

NOTIFY="yes"

USERNAME="rridley"
USERID=1000

DEVICE=$(blkid | grep LUMIX | awk '{print $1}' | tr ':' ' ')

if [ -n "$DEVICE" ]; then
  echo "Found LUMIX sdcard at $DEVICE"

  mount $DEVICE /mnt/lumix
  rsync -rtv --chown $USERNAME:$USERNAME --exclude ".Trash*" /mnt/lumix/DCIM/100_PANA/ /mnt/nas/photos/Camera/
  umount /mnt/lumix

  if [ "$NOTIFY" = "yes" ]; then
    sudo -u $USERNAME DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$USERID/bus notify-send -a "LUMIX Sync" -u normal "Lumix Sync" "SD Card has been synced"
  fi
fi;

Then I created a really simple Service definition to execute the script in /etc/systemd/system/sync-lumix.service

[Unit]
Description=Sync Lumix SD card

[Service]
Type=oneshot
ExecStart=/usr/local/bin/lumix.sh

[Install]
WantedBy=multi-user.target

You can test that everything works up to this point by just running the service systemctl start sync-lumix with the SD Card inserted.

Finally, where the magic happens - I created this udev rule in /etc/udev/rules.d/90-lumix.rules Note: It was important for me to prefix this with 90 as anything lower didn't seem to trigger the rule for me for some reason.

ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="LUMIX", ENV{SYSTEMD_WANTS}+="sync-lumix.service"

What this is saying is to look for when we add a new block device that has the label "LUMIX" - which is the default my camera gives sdcards when formatted. When that happens, start the service sync-lumix.

Reload the udev rules by running udevadm control --reload