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).

enter image description 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.