After digging into this further myself I found that the com.apple.locate
task (/System/Library/LaunchDaemons/com.apple.locate.plist
) launches a script at /usr/libexec/locate.updatedb
.
It appears inside that script that Time Machine volumes are intended to be excluded, however the path for matching them is */Backups.backupdb"
which only matches old-style (HFS+) Time Machine volumes, as APFS Time Machine volumes are structured very differently.
The correct solution to this problem would be to provide different exclusion rules, but both the launchd task and script are covered by System Integrity Protection, though there is a way around this.
Another part of the problem is that backupd
has a habit of leaving snapshots mounted under /Volumes/.timemachine
when it no longer needs them, which appears to be where the find
process is getting stuck, so unmounting these provides another possible solution.
So this gives two possible solutions (both will require you to be logged in as root to do this, if you don’t know how or are not comfortable with the command line then you may just have to wait for Apple to fix this):
Add Custom Exclusions to /usr/libexec/locate.updatedb
- Copy
/usr/libexec/locate.updatedb
to another location (such as/usr/local/lib
) - Find the line:
: ${PRUNEPATHS="/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb"} # unwanted directories
- After
*/Backups.backupdb
add/Volumes/.timemachine
like so:: ${PRUNEPATHS="/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb /Volumes/.timemachine"} # unwanted directories
- Copy
/System/Library/LaunchDaemons/com.apple.locate.plist
to/Library/LaunchDaemons
- Edit
/Library/LaunchDaemons/com.apple.locate.plist
to point to your custom script (/usr/libexec/locate.updatedb
to/usr/local/lib/locate.updatedb
). - Unload the old task using:
launchctl unload -w /System/Library/LaunchDaemons/com.apple.locate.plist
- Load your replacement task using:
launchctl load /Library/LaunchDaemons/com.apple.locate.plist
OR
Unmount Leftover Snapshots
- Turn off automatic Time Machine backups in System Preferences.
- Create a launchd task that will trigger Time Machine, and cleanup snapshot mounts afterwards (see below for a sample task).
- Load the launchd task with:
launchctl load /Library/LaunchDaemons/custom.backup.plist
/Library/LaunchDaemons/custom.backup.plist
<?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>custom.backup</string>
<key>ProgramArguments</key>
<array>
<string>bash</string>
<string>-c</string>
<string><![CDATA[
if tmutil startbackup --auto --block --rotation; then
mount | grep -o '/Volumes/.timemachine/.*\.backup' | while read mountpoint; do
diskutil unmount ${mountpoint}
done
fi
]]></string>
</array>
<key>StartCalendarInterval</key>
<dict>
<string>Minute</string>
<integer>0</integer>
</dict>
</dict>
</plist>
This will run Time Machine every hour, on the hour (or after waking, if your computer was asleep at the time), and after running successfully it will look for all snapshots mounted under /Volumes/.timemachine
and try to unmount them, so com.apple.locate
won’t be able to index them.
While this option is a little cleaner (and is useful if you want more control over when Time Machine runs and what happens before and after it does) it has the downside of timing since there’s no guarantee com.apple.locate
won’t run while snapshots are still mounted, though with the mounts being cleaned up the chance of that should be low.