How to automatically mount network share when iPhone backup screen is opened in Finder?
I would like to trigger a script that mounts a drive when I open the iPhone's device page in Finder (like shown here).
Currently, I have the iPhone backups in an APFS volume, which is inside a SparseBundle, which is on a SMB share on my NAS.
Before running an iPhone backup, I mount the drive by manually running a shell script.
Since I work on a MacBook the LAN with my NAS is not always available, hence the detour with mounting manually. But triggering the mount process automatically when entering the page in finder seems a good idea.
- Is there any event fired to attach such a script to?
- Or maybe there is any other sensible method to mount the drive automatically?
Solution 1:
Yes, a script can be triggered when the iPhone is connected...
When the iPhone is connected to the Mac, the following file gets modified:
/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist
Using a Launch Agent with a WatchPaths
key it can be determined if the iPhone is connected to the Mac when the NetworkInterfaces.plist file is modified.
For testing purposes, I created the launch agent as:
$HOME/Library/LaunchAgents/com.me.iphone.connected.plist
Contents of the com.me.iphone.connected.plist file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.me.iphone.connected</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/iPhone</string>
</array>
<key>RunAtLoad</key>
<false/>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist</string>
</array>
</dict>
</plist>
In the XML PLIST file, /usr/local/bin/iPhone is a shell script that gets executed when there is a change to the NetworkInterfaces.plist file and the contents of the shell script is:
#!/bin/zsh
iPhone="$(/usr/bin/defaults read /Library/Preferences/SystemConfiguration/NetworkInterfaces.plist | /usr/bin/grep -m 1 -o 'iPhone')"
if [[ -n "$iPhone" ]]; then
if [[ -d "/Volumes/Data" ]]; then
if [[ ! -d "/Volumes/iPhone Backup" ]]; then
open "/Volumes/Data/iPhone_Backup.sparsebundle"
fi
fi
fi
When the example shell script is executed it assumes I'm already connected to the Network Share, in this example it's "Data", but it first sets the value of the iPhone
variable by using the defaults
command to read the .plist
file and pipes its output to grep
to return the first occurrence of "iPhone" if found. If the iPhone is connected, then iPhone="iPhone"
and the test in the first if
statement succeeds.
The next test succeeds if I am connected to Data, and the subsequent test succeeds if I'm not already connected to my iPhone Backup sparsebundle. It's coded in this manner so as not to try opening the sparsebundle if it's already mounted if the NetworkInterfaces.plist file is modified again while the sparsebundle is already mounted. In other words, the sparsebundle is only opened if it's not already mounted.
If you also want the mounting of the SMB share to occur in the, e.g. iPhone
, shell script, you can add the following example command directly after the opening of the first if
statement. In other words, literally between the first two if
statements:
/usr/bin/osascript -e 'mount volume "smb://user:@server/share"'
This uses AppleScript code to mount the target share and assumes the credentials are already stored in your Keychain. It also is not problematic if the SMB share is already mounted, then the command just fails silently.
Notes:
Had you included the script or code you are already using, I would have created a working example that would have incorporated it, however what I've submitted is an example that works for me tested under macOS Catalina.
I recommend you read the manual pages for launchctl
, launchd.plist
and launchd
. You can read the manual page for command
in Terminal by typing command
and then right-click on it and select: Open man Page
After creating the $HOME/Library/LaunchAgents/com.me.iphone.connected.plist
file I loaded it using the launchctl
command, e.g.:
cd "$HOME/Library/LaunchAgents/"
launchctl load com.me.iphone.connected.plist
Once loaded, it will automatically load when you login to your account, so you shouldn't need to do it manually again under normal circumstances. To unload it, use the unload
subcommand with the launchctl
command.
After unloading it, you can use the disable
subcommand so it doesn't load again or you can delete the .plist
file, if/when you want to undo changes you've made to your system.