Trigger ADB backup when phone is connected to PC

I’m using an Arch Linux based distro and trying to automate copying the local Seedvault backup when it’s connected. I’m able to trigger a copy with adb pull /storage/<sdcard serial>/.SeedVaultAndroidBackup/ but I’m not able to get it triggered with udev rules.

This is in the /etc/udev/rules.d/50-fp5.rules file:
ACTION=="add", SUBSYSTEM=="usb", KERNEL=="android_adb", ATTR{ID_SERIAL}=="Fairphone_FP5_<serial>", MODE="0660", TAG+="uaccess", RUN+="systemd-run --machine=user@.host --user notify-send 'Hello' 'Making backups'"

But it never triggers the test notification, even though doing it manually does.
I’ve checked with udevadm control --log-priority=debug and journalctl -f but I don’t see the rule triggering ever. I tried without filtering for SUBSYSTEM and without ATTR but the same result.

I can clearly see “android_adb” appearing in /dev when I plug it in.

give the udev rule the absolute path to systemd-run, as in

ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee7", MODE="0660", TAG+="uaccess", RUN+="/usr/bin/systemd-run --user --machine=user@.host notify-send 'Hello' 'Making backups'"

I used the ATTR attributes as given my lsusb -vv and saw it working

1 Like

I tried this after your message, even using just the serial (so using ATTR{iSerial} with the lsusb output for the ADB driver, and it won’t trigger. After changing the rule to use your ATTR filters, it is triggered and shows the notification. But it triggers on each Android phone I connect.

5-2: sd-device: Created database file '/run/udev/data/c189:526' for '/devices/pci0000:00/0000:00:08.1/0000:0e:00.3/usb5/5-2'.
run-p10510-i10511.service: Deactivated successfully.
5-2: Device processed (SEQNUM=5386, ACTION=add)
5-2: sd-device-monitor(worker): Passed 1155 byte to netlink monitor.
5-2:1.0: Device ready for processing (SEQNUM=5387, ACTION=add)
5-2:1.0: sd-device-monitor(manager): Passed 333 byte to netlink monitor.
5-2: SEQNUM=5388 blocked by SEQNUM=5387
5-2:1.0: Processing device (SEQNUM=5387, ACTION=add)
5-2:1.0: /usr/lib/udev/rules.d/40-gphoto.rules:9 Failed to run builtin 'usb_id': No such file or directory
5-2:1.0: /etc/udev/rules.d/50-fp5.rules:1 RUN '/usr/bin/systemd-run --machine=user@.host --user notify-send 'Hello' 'Making backups''
5-2:1.0: /usr/lib/udev/rules.d/50-udev-default.rules:20 Importing properties from results of builtin command 'hwdb --subsystem=usb'
5-2:1.0: hwdb modalias key: "usb:v18D1p4EE7d0504dc00dsc00dp00icFFisc42ip01in00"
-2:1.0: /usr/lib/udev/rules.d/50-udev-default.rules:29 Importing properties from results of builtin command 'path_id'
5-2:1.0: /usr/lib/udev/rules.d/80-drivers.rules:5 RUN 'kmod load'
5-2:1.0: sd-device: Created database file '/run/udev/data/+usb:5-2:1.0' for '/devices/pci0000:00/0000:00:08.1/0000:0e:00.3/usb5/5-2/5-2:1.0'.
5-2:1.0: Running command "/usr/bin/systemd-run --machine=user@.host --user notify-send 'Hello' 'Making backups'"
5-2:1.0: Starting '/usr/bin/systemd-run --machine=user@.host --user notify-send 'Hello' 'Making backups''

Thanks, I’m one step further now ! But I’m not seeing a way to filter on this specific device. If I use any attributes (like iSerial) to only trigger on that phone, it won’t trigger.

I finally found the correct syntax to trigger:

/etc/udev/rules.d/80-fp5.rules

ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee7", ATTR{serial}=="xxxxxxxx", RUN+="/usr/bin/systemd-run --machine=user@.host --user notify-send 'Hello' 'Making backups'"

Now it triggers only with the phone with that serial number ! I found the correct syntax for the “serial” with this command:

udevadm info --attribute-walk --path=$(udevadm info --query=path --name=/dev/android_adb)

Which showed it wasn’t “ID_SERIAL”, “iSerial” or “SerialNumber”. Thanks for getting me through this !

great, a backup trigger is a nice thing to have. I had the impression too that the ATTR syntax is strict and used ones I knew to work

1 Like

can you please publish a sinthetic post where you share explaination about what your setting does exactly,
and how to reproduce step by step because it can be usefull for some others with less IT research skill but who are abble to understand the goal and copy paste commands, replace values or filing strings.
they could be numerous here…

thanks in advance.

I also don’t know everything about it but I can certainly try to explain.

To automate running commands or scripts when attaching or disconnecting devices, you can use udev for this functionality. It sees when a USB device is attached or disconnected, for instance.

Wikipedia:

udev (userspace /dev) is a device manager for the Linux kernel. As the successor of devfsd and hotplug, udev primarily manages device nodes in the /dev directory. At the same time, udev also handles all user space events raised when hardware devices are added into the system or removed from it, including firmware loading as required by certain devices.

Some more explanation for Arch Linux: udev - ArchWiki
And for Debian: udev - Debian Wiki
For creating rules: Writing udev rules

Those links already explain it way better than I can. What I can add this is not mentioned often: the syntax for the rules file is very strict and does not let you know when you make an error. I recommend starting with very broad filters (attributes, subsystems, etc) and only test with opening an app or sending a message. Look at my example and don’t forget to replace the “user” part of “user@.host” if your user account is named differently. When you get the basic filtering to work, you can increasingly add filters as required if you need it to trigger on a specific device or a type of devices. When it doesn’t work, figure out why.

My rule:

ACTION=="add"
→ When a device is added with the following filters:

SUBSYSTEM=="usb"
→ USB device

ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee7"
→ A device with this vendor ID and product ID. These correspond to Android ADB drivers, so for me using those drivers, it is detected that an Android smartphone is connected with USB Debug enabled.

ATTR{serial}=="xxxxxxxx"
→ This filters for the specific device that I want to trigger the command on, or it would trigger on each Android smartphone with USB Debug enabled.

RUN+="/usr/bin/systemd-run --machine=user@.host --user notify-send 'Hello' 'Making backups'"
→ This is the command I used to test it working. As I think udev operates as root, so calling an application to open, will not display in the logged in user I guess. This specifically says to send a notification to the “user”-account of the same host-machine. If you want to run more commands, you can just use another RUN+ command at the end, but I recommend to consult the documentation.

2 Likes