« Java and IP Addresses | Main | Squinting at Your Browser »

My Backup Script on OS X

It’s sysadmin script day on Technometria. Earlier, I posted and explained by script for cleaning up unwanted files in Linux. Later this afternoon Kelly Flanagan asked me how I did backups, so I decided to clean up my backup script and post it for all to see.

First, let me explain that my goal here is to produce a copy of my files. I’m not trying to do imcrementals. This protects me from disk failure, but not my own stupidity. I used to use Synchronize! Pro for backups. It had a few really nice advantages. First if created an image and second, it only copied the files that had changed. But it got flaky and would hang, complain about “non-deletable” files and so on. Those problems, combined with the fact that it’s expensive, made me look for another solution.

I started using rsync several months ago to back up my wife’s photos. rsync has been around for years and was actually the result of someone’s dissertation research in the 80’s, if I remember right. I used to use it as a grad student in the 80’s to backup my files form one machine to another. It works across a network, if necessary, and also only copies what’s changed. In fact, I wouldn’t be surprised to find out that Synchronize! Pro was just a fancy front end for rsync.

This script takes a user name as a parameter, and backs up that user to a drive using rsync. The script automatically mounts and unmounts the drive because I hate having the drive spin up every time I go to open or save a file.

#!/bin/bash

USER=$1

echo "Backing up ${USER}"

# backup volume
VOLUME='/Volumes/PantherBackup'

# Get device using  'diskutil info ${VOLUME}'
DEVICE='/dev/disk1s3'

if [ ! -e ${VOLUME} ]
then 
   echo "Mounting ${DEVICE} as ${VOLUME}"
   /usr/sbin/diskutil mount ${DEVICE}
else
   echo "${VOLUME} already mounted"
fi

SRC="/Users/${USER}/"
DEST="${VOLUME}${SRC}"

echo "Backing up " ${SRC} " to " ${DEST}

sudo rsync -av --timeout=120 --delete ${SRC} ${DEST}

echo "Unmounting ${VOLUME}"
/usr/sbin/diskutil eject ${VOLUME}

The script is intentionally chatty and OS X specific. For example, the disk mounting and unmounting uses the OS X diskutil command. To mount the device, you need the device name. You can get that with diskutil (or it’s graphical sibling DiskUtil) by asking for the “info” on the volume when it’s mounted.

Note that I run rsync as root since there are some root owned files in my directory space (from CPAN). I modified the /etc/sudoers file (with visudo) so that I can run rsync as root without a password. Be careful if you do this. It’s easy to make a mistake in the sudoer syntax and make it so you can’t use sudo anymore.

Posted by windley on April 4, 2007 8:47 PM

See related posts:

3 Comments

Comment from Eric at April 5, 2007 9:16 AM

Cool... here's the one I use. I put it on my USB drive and when I plug the usb drive in it runs the script automatically.

It uses machine name so I can back up multiple computers w/ it.

rsync also works over the network so I could also have it run hourly to backup to a hosted server running linux.

autorun.sh
## identify mount point of this device
## cd to mount point
## then run backup machine.sh
cd /media/usbdisk
gksudo /media/usbdisk/run.backup.machine.sh

run.backup.machine.sh
#!/bin/bash
rm err.txt
gnome-terminal -t 'Error Log' -x tail -f err.txt &
./backup.machine.sh 2> err.txt


backup.machine.sh
#!/bin/bash

SOURCE_DIR="/backup"

GEN="000"

TARGET_DIR="`hostname`/$GEN"

BACKUP_LOG="$TARGET_DIR/backup/`date +%F`.log"

mkdir -p "$TARGET_DIR/backup"
touch $BACKUP_LOG

### see what's going on
gnome-terminal -t 'Backup Log' -x tail -f $BACKUP_LOG &
gnome-terminal -t 'Watch Disk Space' -x watch df -h &

echo `date` 1>&2 >> $BACKUP_LOG
echo "Logging to file: $BACKUP_LOG" 1>&2 >> $BACKUP_LOG
echo "rsync from --> to" 1>&2 >> $BACKUP_LOG
echo "$SOURCE_DIR --> $TARGET_DIR" 1>&2 >> $BACKUP_LOG

rsync -aritPL \
--exclude '*.Trash*' \
--exclude '*Tunes*' \
--exclude '*Music*' \
--exclude '*.wine*' \
--exclude '*.ies4linux*' \
--exclude '*.blender*' \
--exclude '*.tmp*' \
--exclude '*.Temp*' \
--exclude '*.temp*' \
--exclude '*Cache*' \
--exclude '*cache*' \
--exclude '*.thumbnail*' \
--exclude 'link\ to*' \
--exclude '*Temporary\ Internet\ Files*' \
$SOURCE_DIR \
$TARGET_DIR \
1>&2 >> $BACKUP_LOG

echo `date` 1>&2 >> $BACKUP_LOG
echo "Done" 1>&2 >> $BACKUP_LOG


Comment from Matt at April 25, 2007 3:06 PM

For OS X, should you use:

rsync -avE

(the -E is for Resource Forks)?

Comment from JD at May 31, 2007 10:57 AM

I'm confused by your choice of -aritPL, Eric. Firstly, -a subsumes the functionality of -r and -t, so there's no need to use all three. Secondly, my version of rsync doesn't have -i, so I don't know what that does. (I'm using rsync 2.6.3 on 10.4.9.) -a implies -l, so I'm not sure if using -L later in the arguments overrides that.

I'm using -SExa in my backup script. The logic behind -SExa is that I want
-S to handle sparse files efficiently,
-E for extended attributes,
-x to not cross filesystems (because I'm backing up one entire filesystem),
-a for all the various archivey stuff it implies.

Leave a comment

I encourage you to leave a comment below. Your email address will not be displayed on Technometria, but allows me to communicate with you directly. Your email address won't be displayed, but will be used to compute a MicroID for your comment.