Using CRON to Control TimeMachine Backups

September 02, 2009

My office setup includes two Macintosh computers, a Mac Pro and a MacBook Pro. I have a 500 GB FireWire drive attached to the Mac Pro that I use for TimeMachine backups. Through the power of a DNS entry for the Mac Pro, and this article on Network Time Machine backups to another Mac, I am able to backup the MacBook Pro, wirelessly, to the TimeMachine drive on the Mac Pro.

The only problem with this arrangement is that the MacBook Pro attempts to back itself up regardless of my location. When I'm at home at it is connected to our home network it can locate my work computer (via the DNS entry) and it tries to use our less-than-significant upload bandwidth to backup once an hour. The simple solution is to turn TimeMachine off when I am at home. Of course that means remembering to turn it back on again the next day I'm at work. On occasion the simple solution has meant the MacBook Pros backups are a week or more behind.

A better solution would be a script or automated action that would turn TimeMachine on or off. Since I work relatively stable hours a cron job coupled with code to activate or deactivate TimeMachine would suffice.

You can turn TimeMachine on or off via Terminal using this defaults command:

defaults write /Library/Preferences/com.apple.TimeMachine AutoBackup -boolean [YES|NO]

I created two bash scripts, one to turn TimeMachine on:

#!/bin/bash
defaults write /Library/Preferences/com.apple.TimeMachine AutoBackup -boolean YES

And another to turn it off:

#!/bin/bash
defaults write /Library/Preferences/com.apple.TimeMachine AutoBackup -boolean NO

The final step is to create two cron entries, one for 8 am Monday through Friday to run the "on" script from above. And the second for 5 pm Monday through Friday to run the "off" script from above. Crontab entries are in this order: minute hour day-of-month month day-of-week what-to-do. The day-of-week entry uses either 0 or 7 for Sunday, with Monday as 1, Tuesday as 2, and so forth. So the "on" script entry would look like this: 0 8 * * 1-5 ~/bin/timeMachineon.sh and the "off" script entry would look like this: 0 8 * * 1-5 ~/bin/timeMachineoff.sh.

Here's my completed crontab:

# minute hour day-of-month month day-of-week what

# activate TimeMachine zero minutes past 8 am M-F
0 8 * * 1-5 ~/bin/timeMachineon.sh

# deactivate TimeMachine zero minutes past 5 pm (17) M-F
0 17 * * 1-5 ~/bin/timeMachineoff.sh

Now TimeMachine only runs during working hours when I am (presumably) on the work network.

Update 1: The evening cron job fails to run when the laptop is closed, i.e., sleeping, when 5 pm rolls around. Cron is a useful tool but it has to be awake to run. I've changed the evening cron time to 4 pm, a time I am almost always still at work. I am considering adding a second evening crontab entry, say for 7 or 8 pm in case the 4 o'clock instance is missed for some reason. A better solution would be a network aware triggering of the scripts, running the on script only when the work network is detected, and the off script for all other networks.

Update 2: Here's the latest solution, based on Josh's comments.

I created a script called login-hook.sh, which is the target of:

sudo defaults write com.apple.loginwindow LoginHook ~/bin/login-hook.sh

This script tests to see if a TimeMachine control script is running at every login, and starts it if necessary:

#!/bin/bash
# login-hook.sh

if [ "$(ps ax | grep tm-control.sh | grep -vc grep)" -lt 1 ]; then
    sudo -u mhn /Users/mhn/bin/tm-control.sh &
fi

And tm-control.sh runs the Python script Josh supplied every 30 minutes (1800 seconds), in effect simulating a cron job, but leveraging the network awareness of the Python script. Here's tm-control.sh:

#!/bin/bash
# tm-control.sh

while [ 1 ]; do
    python ~/bin/TM_off_on.py
    sleep 1800
done

Update 3: Getting LoginHook to work is a bit finicky. By using defaults read com.apple.loginwindow LoginHook, you can display the current setting, if any, this attribute has. defaults delete com.apple.loginwindow LoginHook will allow you to remove the setting. Make sure you have your login-hook.sh, and the script it calls in place prior to establishing the hook and you should be okay.

Author's profile picture

Mark H. Nichols

I am a husband, cellist, code prole, nerd, technologist, and all around good guy living and working in fly-over country. You should follow me on Twitter.