I have some sensitive data that I want to be backed up frequently and also on the go or at work when my Time Machine disk is not available. The reason is not that I want to protect that data from being lost due to a disk crash or something, more like protecting it from stupid changes I make or an application that might corrupt it. The idea came to me when Evernote – which is really great, I use it for a lot for notes and ideas – somehow magically erased several of my notes. I could restore them from my Time Machine backup, but I thought “Wouldn’t it make sense to automatically backup my notes every some minutes and be able to do diffs and all the other nice things with them? And wouldn’t it be great if all this could work offline?”.
Aha, a Git repository!
And a shell script!
And some automated periodic calling of that script!
I’ll show you how to do it, here we go.
In your ~/Library/Scripts folder create a file git-backup.sh and put this code inside:
#!/bin/sh echo "\n---" # Abort if any command fails set -e # Print current date and working directory echo "$(date) - $(pwd)" # Add all files to index -> also track new files echo "Adding all changes..." git add --all . # Commit all echo "Committing all changes..." git ci -m "<< launchd auto-commit >>"
(Doubleclick the code to select all)
Then in ~/Library/LaunchAgents create a file like yourdomain.yourbackup.plist – e.g. for my Evernote backup I used net.ptrbrtz.evernote-git-backup.plist – and put this inside:
<?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>Debug</key> <false/> <key>Label</key> <string>net.ptrbrtz.evernote-git-backup</string> <key>LowPriorityIO</key> <true/> <key>WorkingDirectory</key> <string>/Users/peter/Library/Application Support/Evernote</string> <key>ProgramArguments</key> <array> <string>/Users/peter/Library/Scripts/git-backup.sh</string> </array> <key>StandardErrorPath</key> <string>/Users/peter/Library/Application Support/Evernote/net.ptrbrtz.evernote-git-backup.log</string> <key>StandardOutPath</key> <string>/Users/peter/Library/Application Support/Evernote/net.ptrbrtz.evernote-git-backup.log</string> <key>StartInterval</key> <integer>1800</integer> </dict> </plist>
You’d have to change the marked lines to your needs.
- WorkingDirectory names the directory whose content will be backed up. You’ll have to create a Git repository there using git init yourself, I guess you know how to do that.
- StandardErrorPath/StandardOutPath should name a file where you want the shell output to be routed to.
- StartInterval sets how often the backup runs. It’s given in seconds, 30 minutes * 60 = 1800 seconds. If you want to set specific dates and times here instead, have a look at the documentation.
Now for the automated calling of the launch agent you just created. We use launchctl for that.
Tell launchctl about your task by doing:
launchctl load ~/Library/LaunchAgents
Now check if launchctl really knows about your launch agent now:
launchctl list | grep "net.ptrbrtz.evernote-git-backup"
You should see something like:
- 0 net.ptrbrtz.evernote-git-backup
Depending on the interval you set, you soon should see your StandardErrorPath/StandardOutPath file popping up – better go check if everything went fine. If you placed it in the repository directory like I did it, you could also go ahead and put it on the Git ignore list to prevent it from being backed up, too.
If you ever make changes to your launch agent plist, make sure you remove it from lauchctl and put it back in to apply your changes:
launchctl remove net.ptrbrtz.diploma-thesis-git-backup launchctl load ~/Library/LaunchAgents
You can create as many automated backups as you want. For every new repository just repeat steps two and three.