Hourly macOS Network Backup Using rsync and launchd (macOS 10.11 El Capitan)
Overview
This procedure creates an automated hourly backup that:
- Copies files from a source folder to a mounted network share.
- Does not delete or modify the source files.
- Runs automatically every hour using
launchd. - Displays a Notification Center alert only when a backup fails.
- Logs failures to a text file.
- Can easily be reconfigured for different client locations by changing the destination volume name.
Step 1: Identify the Source Folder
Open Terminal and navigate to the folder you want to back up.
cd ~/Documents
pwd
Example output:
/Users/dean/Documents
Suppose the folder you want to copy is:
/Users/dean/Documents/CaseFiles
Record this path.
Step 2: Determine the Destination Volume Name
Mount the network share.
In Finder:
Go → Connect to Server
Example:
smb://Office-Mac
After connecting, determine the mounted volume name:
ls /Volumes
Example output:
Macintosh HD
OfficeBackup
The mounted volume name is:
OfficeBackup
Record this name.
Step 3: Create a Scripts Folder
Create a folder to store the backup script.
mkdir -p ~/Scripts
Verify:
ls -ld ~/Scripts
Step 4: Create the Backup Script
Create the script file:
nano ~/Scripts/hourly_backup.sh
Paste the following script:
#!/bin/bash
SOURCE="/Users/dean/Documents/CaseFiles"
DEST="/Volumes/OfficeBackup"
if [ ! -d "$DEST" ]; then
/usr/bin/osascript <<EOF
display notification "Destination volume is not mounted." with title "Backup Error"
EOF
exit 1
fi
/usr/bin/rsync -av --ignore-existing "$SOURCE/" "$DEST/"
RESULT=$?
if [ $RESULT -ne 0 ]; then
case $RESULT in
3) ERROR="Source or destination unavailable" ;;
10) ERROR="Network communication error" ;;
11) ERROR="File I/O error" ;;
12) ERROR="Transfer protocol error" ;;
20) ERROR="Transfer interrupted" ;;
23) ERROR="Partial transfer due to file access problem" ;;
24) ERROR="Source file changed during transfer" ;;
30) ERROR="Network timeout" ;;
*) ERROR="Unknown rsync error (code $RESULT)" ;;
esac
/usr/bin/osascript <<EOF
display notification "$ERROR" with title "Backup Error ($RESULT)"
EOF
echo "$(date): $ERROR" >> "$HOME/backup.log"
fi
Save and exit:
Control-O
Return
Control-X
Step 5: Make the Script Executable
chmod +x ~/Scripts/hourly_backup.sh
Verify:
ls -l ~/Scripts/hourly_backup.sh
You should see executable permissions:
-rwxr-xr-x
Step 6: Test the Script Manually
Run the script:
~/Scripts/hourly_backup.sh
If the destination is mounted and files copy successfully, the script is functioning correctly.
Step 7: Test Failure Notifications
Temporarily edit the script:
nano ~/Scripts/hourly_backup.sh
Change:
DEST="/Volumes/OfficeBackup"
to:
DEST="/Volumes/DoesNotExist"
Run:
~/Scripts/hourly_backup.sh
You should receive a Notification Center alert indicating that the destination volume is not mounted.
Restore the correct destination afterward.
Step 8: Create the LaunchAgents Folder
mkdir -p ~/Library/LaunchAgents
Step 9: Create the LaunchAgent Configuration
Create the LaunchAgent file:
nano ~/Library/LaunchAgents/com.dean.hourlybackup.plist
Paste:
<?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.dean.hourlybackup</string>
<key>ProgramArguments</key>
<array>
<string>/Users/dean/Scripts/hourly_backup.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>3600</integer>
</dict>
</plist>
Replace dean with the actual username on the Mac.
Save and exit.
Step 10: Load the LaunchAgent
Load the job:
launchctl load ~/Library/LaunchAgents/com.dean.hourlybackup.plist
Verify that it is loaded:
launchctl list | grep hourlybackup
Expected output:
com.dean.hourlybackup
Step 11: Trigger an Immediate Test Run
Instead of waiting an hour:
launchctl start com.dean.hourlybackup
The script should execute immediately.
Changing Locations (Lab vs Client Site)
The only value that should need changing is the destination volume.
Determine the mounted volume name:
ls /Volumes
Example:
Macintosh HD
LabBackup
Edit the script:
nano ~/Scripts/hourly_backup.sh
Change:
DEST="/Volumes/OfficeBackup"
to:
DEST="/Volumes/LabBackup"
Save and exit.
No LaunchAgent changes are required.
The next scheduled run will automatically use the new destination.
Reloading the LaunchAgent
You only need to reload the LaunchAgent if the .plist file changes.
Unload:
launchctl unload ~/Library/LaunchAgents/com.dean.hourlybackup.plist
Reload:
launchctl load ~/Library/LaunchAgents/com.dean.hourlybackup.plist
Useful Commands
View Recent Errors
tail -20 ~/backup.log
Check Mounted Volumes
ls /Volumes
Run the Script Manually
~/Scripts/hourly_backup.sh
Verify LaunchAgent Status
launchctl list | grep hourlybackup
Notes
- The source files are never deleted.
- Existing files on the destination are not overwritten because
--ignore-existingis used. - A Notification Center alert appears only when an error occurs.
- Failed transfers are logged to
~/backup.log. - The destination network share must be mounted before the backup runs.
- The Mac must be logged in for Notification Center alerts to appear.