I wrote a simple script and udev rule a few years ago to automatically backup my phone (running Replicant OS, a free, FSF-approved Android distribution) to my computer when I plug it to a USB port. I just published those scripts after some clean-up on a git repository and wrote instructions on how to set it up.
I know there are plenty of Android applications to backup my data and upload them somewhere via Internet. But my phone is rarely connected, the Wi-Fi is usually turned off and I have no data plan. Instead I do plug my phone to my computer on a regular basis to recharge it, so it seemed obvious to automatically trigger a backup of my phone via USB.
udev can be used to detect events, like plugging-in a device, and trigger actions based on these events. In my case, the udev rule looks like this:
ACTION=="add", SUBSYSTEMS=="usb", ENV{ID_SERIAL_SHORT}=="XXXXXXXXXXXXXXXX", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}+="android-backup@$env{ID_SERIAL_SHORT}.service"
Where ID_SERIAL_SHORT
is used to uniquely identify my phone. The rule
triggers the android-backup@.service systemd unit (in user mode, no need to run
it as root).
The systemd unit is very simple, there is no need to specify an [Install]
section, targets or anything like that since it is triggered directly by udev:
[Service]
Type=oneshot
ExecStart=%h/.local/bin/android-backup.sh %I
So the unit simply calls the following shell script:
#!/bin/sh
export DISPLAY=0:0
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
BACKUP_DIR=~/replicant-backup/
RSYNC_EXCLUDE=~/.config/android-backup.exclude
notify-send "Android Backup" "Starting Android backup"
(
set -e
mkdir -p "$BACKUP_DIR"
adb wait-for-device 2>&1 |(grep -Ev "^(\* daemon not running; starting now at|* daemon started successfully$)" || true)
adb root
adb wait-for-device
adb shell rsync --daemon --no-detach --config=/system/etc/rsyncd.conf &
adb forward tcp:6010 tcp:873
sleep 2
rsync -av --chmod u+rwX --delete --delete-excluded --exclude-from "$RSYNC_EXCLUDE" rsync://localhost:6010/root/ $BACKUP_DIR
adb forward --remove tcp:6010
adb shell pkill rsync
)
if [ $? -ne 0 ]; then
notify-send "Android Backup" "Backup terminated with errors. See journalctl --user -eu android-backup for details"
else
notify-send "Android Backup" "Backup terminated successfully"
In this script, I first start adb (as root so it can have access to the whole system) and start a rsync daemon on the OS running on the phone and forward its TCP port through adb. I can then start a normal rsync from my computer to fetch all the files and directories. The destination directory (on my computer) is included in my daily backup, thus I automatically have incremental copies of my phone's data.