Version-control the backup LaunchAgent, with the path trap written down
The plist existed only in the transfer bundle, in a version that still pointed at ~/Documents — the path that macOS TCC silently refuses to let launchd execute from, and the reason the nightly backup did nothing for eight days while logging nothing. Captured from the ingest Mac as it now runs, with a README explaining why the checkout must live outside ~/Documents and why the script cannot glob the Drive folder. Both are easy to undo by accident and expensive to rediscover. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2ee1b18dc3
commit
d188308d1f
@@ -0,0 +1,32 @@
|
|||||||
|
# Deployment bits that live outside the app
|
||||||
|
|
||||||
|
## `org.waterschurch.checklist-drive-backup.plist`
|
||||||
|
|
||||||
|
The LaunchAgent that runs the nightly off-site backup. It belongs in
|
||||||
|
`~/Library/LaunchAgents/` on **one** always-on Mac — currently the ingest Mac
|
||||||
|
(`NA-Ingest`, account `Studio`). Install with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp deploy/org.waterschurch.checklist-drive-backup.plist ~/Library/LaunchAgents/
|
||||||
|
launchctl load ~/Library/LaunchAgents/org.waterschurch.checklist-drive-backup.plist
|
||||||
|
```
|
||||||
|
|
||||||
|
**The path in it matters more than it looks.** It points at `~/checklist-app`, not
|
||||||
|
`~/Documents/…`, and that is not cosmetic: macOS TCC does not let `launchd` execute
|
||||||
|
anything inside `~/Documents`, `~/Desktop` or `~/Downloads`. When the project lived in
|
||||||
|
`~/Documents` the agent failed instantly every night with
|
||||||
|
|
||||||
|
```
|
||||||
|
/bin/bash: …/backup-to-drive.sh: Operation not permitted
|
||||||
|
```
|
||||||
|
|
||||||
|
logging nothing, for eight days, because the script never started. Keep the checkout
|
||||||
|
outside those folders on any machine that runs this agent.
|
||||||
|
|
||||||
|
The same restriction applies one level down: `launchd` can stat a named file under
|
||||||
|
`~/Library/CloudStorage` but cannot list the directory, which is why
|
||||||
|
`backup-to-drive.sh` checks explicit filenames instead of globbing.
|
||||||
|
|
||||||
|
A LaunchAgent only fires while that user is logged in. If the Mac is asleep at 04:15,
|
||||||
|
launchd runs the job shortly after it wakes, so a missed night self-heals — but a Mac
|
||||||
|
that is off, or logged out, backs nothing up and says nothing.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?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>org.waterschurch.checklist-drive-backup</string>
|
||||||
|
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/Users/Studio/checklist-app/backup-to-drive.sh</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<!-- 04:15, comfortably after the NAS writes its nightly backup at 03:30. A LaunchAgent
|
||||||
|
only runs while this user is logged in; if the Mac was asleep or off at 04:15,
|
||||||
|
launchd fires the job once shortly after it wakes, so a missed night self-heals. -->
|
||||||
|
<key>StartCalendarInterval</key>
|
||||||
|
<dict>
|
||||||
|
<key>Hour</key><integer>4</integer>
|
||||||
|
<key>Minute</key><integer>15</integer>
|
||||||
|
</dict>
|
||||||
|
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<false/>
|
||||||
|
|
||||||
|
<!-- The script keeps its own timestamped log; these catch anything it cannot, such as
|
||||||
|
the interpreter failing outright. -->
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>/Users/Studio/Library/Logs/checklist-drive-backup.out.log</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>/Users/Studio/Library/Logs/checklist-drive-backup.err.log</string>
|
||||||
|
|
||||||
|
<!-- expect and node live in the standard locations; launchd's default PATH is minimal. -->
|
||||||
|
<key>EnvironmentVariables</key>
|
||||||
|
<dict>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Reference in New Issue
Block a user