Mac OS X bootable backup drive with rsync

I’ve started using a backup strategy based on that originally described by Jamie Zawinski and subsequently covered in Jeff Atwood’s What’s your backup strategy? article. It works by incrementally backing up your data to a bootable clone of your computer’s internal drive, in order to replace the internal drive when it fails.

This post is mainly to document – for myself as much as anything – the process I went through in order to implement an incremental backup strategy in OS X 10.6. Use at your own risk. Feel free to suggest improvements if you know of any.

Formatting and partitioning the drive

With your backup drive in its enclosure, connect the drive to your Mac and open the Disk Utility application.

  1. Click on the disk’s name. This should bring up a “Partition” tab in the right panel.
  2. Click on the “Partition” tab.
  3. Under “Volume scheme” select the number of partitions you need. Probably “1 partition” if it is to match your internal disk.
  4. Under “Name” enter the volume name you want to use, e.g., “Backup”.
  5. Under “Format” select “Mac OS X Extended (Journaled)”, which is necessary if the disk is to be bootable.
  6. Click “Options” and check that “GUID Partition Table” is selected.
  7. Click “Apply”.

This will format and partition the disk. The partition(s) should now show up in the Finder and on the Desktop.

Enable ownership permissions

The new partition needs permissions to be enabled to avoid chown errors when using rsync. To do this, select the partition and view its information page (using “Get Info” or Command+I). Expand the “Ownership & Permissions” section and uncheck “Ignore ownership on this volume”

Backup script

The backup script relies on using rsync – a fast and versatile file copying tool that is included in OS X – to manage the copying and moving of data between volumes. It offer a wide variety of options and only copies the differences between the source files and the existing files in the destination, making it ideal for incremental backups. You can find out more about rsync in the rsync documentation.

The following is the contents of a script I’ve named rsync_backup.sh. I’m using it to backup all of the data on my internal disk, with a specified set of exceptions contained within a file called rsync_excludes.txt.

#!/bin/sh

PROG=$0
RSYNC="/usr/bin/rsync"
SRC="/"
DST="/Volumes/Backup/"

# rsync options
# -v increase verbosity
# -a turns on archive mode (recursive copy + retain attributes)
# -x don't cross device boundaries (ignore mounted volumes)
# -E preserve executability
# -S handle spare files efficiently
# --delete delete deletes any files that have been deleted locally
# --exclude-from reference a list of files to exclude

if [ ! -r "$SRC" ]; then
 /usr/bin/logger -t $PROG "Source $SRC not readable - Cannot start the sync process"
 exit;
fi

if [ ! -w "$DST" ]; then
 /usr/bin/logger -t $PROG "Destination $DST not writeable - Cannot start the sync process"
 exit;
fi

/usr/bin/logger -t $PROG "Start rsync"

sudo $RSYNC -vaxE -S --delete --exclude-from=$HOME/rsync_excludes.txt "$SRC" "$DST"

/usr/bin/logger -t $PROG "End rsync"

# make the backup bootable
sudo bless -folder "$DST"/System/Library/CoreServices

exit 0

View the Gist. Adapted from the rsync script at Automated OSX backups with launchd and rsync

This is the contents of the rsync_excludes.txt file.

.Spotlight-*/
.Trashes
/tmp/*
/Network/*
/cores/*
/afs/*
/automount/*
/private/tmp/*
/private/var/run/*
/private/var/spool/postfix/*
/private/var/vm/*
/Previous Systems.localized
/Volumes/*
*/.Trash

Adapted from the excludes file at Automated OSX backups with launchd and rsync

Every time the script runs, messages will be written to the system log.

Check that the source (SRC) and destination (DST) paths in the script are correct and match the volume name that you chose when partitioning the disk. Wrapping the $SRC and $DST variables in double quotes ensures that the script will work even if your volume names contain spaces (e.g. “Macintosh Backup”).

The command option --exclude-from tells the script where to find the file containing the exclude patterns. Make sure you either have rsync_excludes.txt in the home directory or that you update this part of the command to reference the full path of the excludes file.

Running the backup script

You can run the script from the command line, or make it executable from the Finder or the Desktop:

  1. Type the following into the command line to ensure that you have permission to execute the script:
    chmod +x /path/to/rsync_backup.sh
  2. Remove the .sh extension from the script.
  3. Create an alias of the script and move it to the Desktop.
  4. Double click the icon to run the backup script.

It’s important to run the script regularly in order to keep the backup in sync with your internal disk. If you have a desktop computer, or you never turn off your laptop, you can automate the running of the script by setting up a cron job.

Checking the disk is bootable

Once you’ve run the backup script, you should test that the backup disk is bootable. To do this, restart your computer and hold down the Alt/Option key. Your backup disk should be presented, with the volume name you chose, as a bootable disk.

When I first booted my backup, the terminal displayed the following line:

dyld: shared cached file was build against a different libSystem.dylib, ignoring cache

According to this article, the fix for this is to update the cache by entering the following into the terminal:

sudo update_dyld_shared_cache -force

That should be everything you need to start implementing an incremental backup strategy when using OS X.

3 comments

#

Mathias Bynens says…

If you’d like to add an icon to your Dock as a shortcut to the build script, you’ll have to create an app out of it. Luckily, Thomas Aylott wrote a script that allows you to very easily create apps from shell scripts.

#

Chris Gillispie says…

Thank you for publishing this script; I plan to use it soon.

I just upgraded to 10.7 Lion and wonder if you foresee any edits I’d need to make in the script to adjust it from 10.6 Snow Leopard.

#

Henrik Cederblad says…

Very neat strategy! I’m curious (like Chris) if anyone’s been using this (as is) in OS X 10.7.

Comment on this post

Please wrap code fragments in <code> tags, wrap blocks of code in <pre><code>, and use JsFiddle to post working examples.