Wednesday, February 1, 2012

Automating rsync on a Mac

For reasons that I won't go into here, I decided that I wanted to sync some of the folders on one of my internal hard drives to another internal drive. This is not a backup system, because old versions of files are not saved (I have Time Machine for that)-- it's just a way to mirror data.

Naturally I thought of using rsync, and the command to copy the files is easy:

sudo rsync -axES --delete /Volumes/MacA/Data /Volumes/MacAMirror/

However, I wanted this to run automatically. I tried using Automator, but I'd have to enter a password each time the thing ran, which I did not want to do. In fact, I wanted it to run at night when I wasn't even here.

My solution? Create a symbolic link to rsync and then edit the sudoers file so that I didn't need to enter a password when running that program. I did this instead of changing my access to the main rsync executable so that I didn't accidentally get myself in trouble some time with rsync.

So first I created a directory to put my symbolic link and shell script in.

~$ mkdir ShellScripts
~$ cd ShellScripts
~/ShellScripts$ ln -s /usr/bin/rsync nopass_sudo_rsync
~/ShellScripts$ ls -l
total 16
lrwxr-xr-x  1 chrisg  staff   14 Jan 27 11:44 nopass_sudo_rsync -> /usr/bin/rsync
-rwxr--r--  1 chrisg  staff  334 Jan 31 12:50 rsync_data.sh

The script file (rsync_data.sh) looks like this:

#!/bin/sh

logger 'Start MacA rsync'
sudo /Users/chrisg/ShellScripts/nopass_sudo_rsync -axES --delete /Volumes/MacA/Data /Volumes/MacAMirror/
logger 'Stop MacA rsync'

Then I edited the sudoers file:

~/ShellScripts$ sudo visudo

I added this line to the Cmnd alias specification section:

Cmnd_Alias JUSTRUN  = /Users/chrisg/ShellScripts/nopass_sudo_rsync

And this line to the User privilege specification

chrisg  ALL=(ALL) NOPASSWD: JUSTRUN

This creates a group of commands called JUSTRUN that chrisg is allowed to run with sudo without a password.

The last step was to create a plist file in /Library/LaunchDaemons.

~/ShellScripts$ cd /Library/LaunchDaemons
/Library/LaunchDaemons$ sudo vi org.chrisg.daily.rsync_data.plist

Here are the contents of org.chrisg.daily.rsync_data.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>org.chrisg.daily.rsync_data</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/chrisg/ShellScripts/rsync_data.sh</string>
  </array>
  <key>StartCalendarInterval</key>
  <dict>
    <key>Hour</key>
    <integer>20</integer>
    <key>Minute</key>
    <integer>05</integer>
  </dict>
</dict>
</plist>

This will run /Users/chrisg/ShellScripts/rsync_data.sh daily at 20:05.

See here for some plist recipes.

Use launchctl to get the automation working immediately instead of waiting for the next reboot.

/Library/LaunchDaemons$ launchctl load org.chrisg.daily.rsync_data.plist