Skip to content

Instantly share code, notes, and snippets.

@ariankordi
Last active February 10, 2024 00:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ariankordi/3c87db7e1363b6fe3d33b9858863fd87 to your computer and use it in GitHub Desktop.
Save ariankordi/3c87db7e1363b6fe3d33b9858863fd87 to your computer and use it in GitHub Desktop.
script that automatically backs up my iphone over wifi using idevicebackup2, avahi-daemon, and netmuxd running as usbmuxd i'm too lazy to explain the rest rn (it's more complex because my jailbreak makes it not work when doing it the correct way)
#!/bin/sh
# udid of device that is already paired and wifi enabled on
udid=""
# todo replace with reverse lookup of the mac address??? but it wouldn't be
# the wifi mac address we know it would have to be the anonymized one
# ip neighbor | grep 02:21:21:21:21:21 | awk '{split($0, a, " dev"); printf a[1]}'
ip="192.168.2.21"
# 24 hours
# time that shall be in between backups
backup_delay="86400"
# find status.plist which would mostly indicate that the backup folder for this device already exists
if [ ! -f ./$udid/Status.plist ]; then
echo "sorry cannot find Status.plist in backup folder if there even is one (if you haven't backed up before, do that manually)"
exit
fi
# see if it is time to backup yet
date_e=$(plistutil -i ./$udid/Status.plist | awk '{split($0, a, "date>"); split(a[2], b, "<"); printf b[1]}')
date_d=$(date -d $date_e +%s)
date_difference=$(expr $(date +%s) - $date_d)
if [ "$1" != "--force" ] && [ $(expr $date_difference \> $backup_delay) -eq 0 ]; then
echo "it is not backup time yet (last backup was $date_difference seconds ago ($(awk "BEGIN{printf\"%.2f\",$date_difference/3600}") hours ago (it is $(awk "BEGIN{printf\"%.2f\",100*$date_difference/$backup_delay}")% there)))"
exit
fi
# after the backup folder is there and it is time to make the backup, continue trying to communicate with the device
# get wifi mac address from pairing configuration in /var/lib/lockdown which is needed to find the device
wifimacaddress=$(grep -i wifimacaddress -A1 /var/lib/lockdown/$udid.plist | awk '{split($0, a, "string>"); split(a[2], b, "<"); printf b[1]}')
if [ -z "$wifimacaddress" ]; then
echo "could not find the mac address of the device from pairing records, which could mean that /var/lib/lockdown isn't accessible or doesn't exist, the device isn't paired, the device doesn't have a mac address, the awk pattern failed... sorry"
exit
fi
# temporary hostname i guess
hostname="guaomy.local"
# pretty much just make blank folders
#arian@debian /u/l/s/jail-for-netmuxd> find
#.
#./var
#./var/run
#./var/lib
#./var/lib/lockdown
#./root
#./usr
#./etc
#./proc
#./sys
#./dev
#./run
#./run/usbmuxd
VAR_RUN_PREFIX="/usr/local/share/jail-for-netmuxd"
# run netmuxd within a bubblewrap sandbox so that its /var/run/usbmuxd is independent
# netmuxd 0.1.2 from 04/20/2022.. the subsequent version i just couldn't get to work
# doesn't really matter since the role of it is JUST to pass the ip to libimobiledevice
(PATH="/usr/local/bin:$PATH" bwrap --die-with-parent --ro-bind / / --bind $VAR_RUN_PREFIX/run /run netmuxd --plist-storage /var/lib || echo "did netmuxd fail to launch????"; kill 0) &
netmuxdpid=$!
# hacky sleep wait for it to start and errythin
sleep 1
# using avahi to publish these services cause this script isn't linux agnostic anyway
# publish iphone's ip address as ephemeral hostname and also omit output from these
avahi-publish-address -R $hostname $ip 2>/dev/null &
publishaddresspid=$!
# publish mobdev2 service that usbmuxd needs to see
avahi-publish-service -H $hostname "$wifimacaddress@" _apple-mobdev2._tcp 32498 2>/dev/null &
publishservicepid=$!
# this is called at the end to clean up the avahi publish processes
kill_publish_processes() {
kill $publishaddresspid
kill $publishservicepid
# pkill -P $$
kill $netmuxdpid
}
# this wait usually works to let avahi services be discovered
sleep 4
# flags for libimobiledevice commands
flags="-n -u $udid"
# make libimobiledevice use the bound socket from netmuxd
export USBMUXD_SOCKET_ADDRESS="UNIX:$VAR_RUN_PREFIX/run/usbmuxd"
#ideviceinfo $flags > /dev/null
#status=$?
#if [ $status -ne 0 ]; then
# echo "ideviceinfo returned $status"
# kill_publish_processes
# exit
#fi
attempts_max=250
attempts=0
# attempt to do ideviceinfo from the device before continuing
while true; do
((attempts=attempts+1))
# get battery info that is used later on, omit output from this because it likes to complainLogLevelMax=alert
batteryinfo=$(ideviceinfo $flags -q com.apple.mobile.battery 2>/dev/null)
status=$?
if [ $status -eq 0 ]; then
# break loop if that returned successful
#echo "device online, continuing backup"
break
fi
# give up when allotted attempts have exceeded
if [ $attempts -gt $attempts_max ]; then
echo "$attempts_max attempts have exceeded trying to find the device, ideviceinfo keeps returning $status, giving up"
kill_publish_processes
pkill -P $$
exit
fi
# wait 4 seconds in between attempts
sleep 4
done
# i only want this to run if the device is connected to a charger
if [ "$1" != "--force" ] && ! echo $batteryinfo | grep -q ExternalConnected\:\ t; then
# doesn't work anymore.. was changed to a battery percentage measurement
#if [ $(echo $batteryinfo | awk '{split($0, a, "BatteryCurrentCapacity: "); printf a[2]}') -lt 74 ]; then
echo "iphone is not charging right now so backup will not be done"
kill_publish_processes
pkill -P $$
exit
#fi
fi
# finally do backup
idevicebackup2 $flags backup .
kill_publish_processes
pkill -P $$
[Unit]
Description=run script that backs up iphone
ConditionPathIsMountPoint=/home/a/iphone
[Service]
Type=oneshot
WorkingDirectory=/home/a/iphone
ExecStart=/home/a/iphone/backup.sh
[Unit]
Description=run script that backs up iphone
[Timer]
OnActiveSec=30m
OnUnitActiveSec=30m
Persistent=true
[Install]
WantedBy=timers.target
updated 2023! i didn't update the readme though bc is anyone actually using this:
this script assumes (requirements?)
* that you are running it in the same directory where an iphone backup has already been made (meaning, where you already did "idevicebackup2 backup .")
* that avahi-daemon is running and you have avahi tools installed, all that junk
* you need netmuxd https://github.com/jkcoxson/netmuxd at a location where you can customize in the script, just look for it
* you also need bwrap and to make a folder called jail-for-netmuxd that just has subdirectories listed in the script
* that your iphone is paired and its pairing record is in /var/lib/lockdown (you can change this)
* there is a part where the backup won't continue if the iphone isn't connected to a charger ~~at 74% battery~~
* the script is meant to be run on a cadence every x minutes (it does the actual more complex checking in the script), and is expected to do an actual backup every 10 hours or so
* the systemd timer and service are included (meant to be run as your user!) to do precisely this. they're called 8h cause that is what it was originally, i don't even know anymore ok. "/home/a/iphone" is the directory that "idevicebackup2 backup ." was run on, in the context of the first assumption.
it will be improved later. this is also more complex than it needs to be, because
1. it broadcasts the iphone, MANUALLY! because my iphone happens to be using unc0ver which makes it not broadcast itself over mDNS, for whatever reason.
2. it relies on running this netmuxd daemon, which cannot be run specifying a custom socket as of its current release, but i know that libimobiledevice tools nowadays use it to just "resolve" at this point and no longer need the daemon at a certain point, when communicating over the network. so in theory, an adhoc daemon that is not even netmuxd that only resolves a device, could be used as well, OR a modified version of libimobiledevice that just specifies an address for which to connect to the device, would be needed. this behavior was needed in the first place from the first thing on this list anyway
i also hope i will make this readme far better soon, i deeply apologize for how bad this is. i mostly wanted to post this in its current state so it's out there
if you get any legitimate use from this, i applaud you
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment