November 11, 2009

I need Backup

Filed under: programming — simsea @ 6:58 am

I needed a backup solution. I had a terabyte hard drive attached to the Mac Mini in the sitting room, but it died rather unexpectedly one day making it a somewhat less attractive backup solution. I gave in and bought a NAS. The Seagate Black Armor 110 NAS actually which I’m really rather enjoying. Their backup software is missing for the Mac, but that’s ok because I have Time Machine. Except that Time Machine is a finicky mistress and doesn’t like some kinds of systems. Particularly, it has issues with NAS not running as AFP. That’s ok, I thought, because there’s a handy “let Time Machine see unsupported drives” command that can be run. It made me happy until I tried it and found that it could not Time Machine up with my NAS. Sadness.

I decided that I would just go the way that I had done before and rsync me up a backup solution. It didn’t take that long to bash (ow, the puns, they burn) out a shell script and have an rsync solution working. Except for another snag. Whatever filesystem the NAS is using is not happy with hard links so my usual rolling backup didn’t want to play. There was a whole lot of failing going on.

I got a bit clever after that and decided that I would write in some more shell scripting to create a disc image (.dmg) as a HFS+J sparse image using hdiutil, attach it, rsync into the disc image and then detach it. No doubt a HFS+J partition would be able to support hard links… Anyway, here’s the script. Comments?

#!/bin/sh

#parameters
useDiskImage=1
diskImageSize=250g
keep=3

source=/Users/simsea
volume=/Volumes/simsea
dest=${volume}/Backups

# check parameters
if [ $keep -lt 3 ]; then
    keep=3
fi

if [ ! -d ${volume} ]; then
    echo Opening volume $volume
    mkdir ${volume}
    mount -t smbfs //simsea@192.168.1.2/simsea ${volume}
fi

if [ ! -d $dest ]; then
    echo Making destination
    mkdir -p $dest
fi

# make a backup disk image
if [ $useDiskImage -eq 1 ]; then
    dest=${dest}/Backup.dmg.sparseimage
    if [ ! -e ${dest} ]; then
	echo Creating disc image $dest
        hdiutil create -size $diskImageSize -type SPARSE -fs HFS+J -volname Backup -autostretch $dest
    fi
    echo Mounting disc image $dest
    hdiutil attach -readwrite $dest
    dest=/Volumes/Backup
fi

echo Deleting ancient backups
num=0
start=`expr $keep - 1`
# delete the oldest backups
while [ -d ${dest}/backup.${num} ]; do
    if [ $num -ge $start ]; then
        echo Deleting ${dest}/backup.${num}
        rm -rf ${dest}/backup.${num}
    fi
    num=`expr $num + 1`
done

for ((i = $start; i > 0; --i)); do
    other=`expr $i - 1`
    echo Moving ${dest}/backup.$other to ${dest}/backup.$i
    mv ${dest}/backup.$other ${dest}/backup.$i
done

echo Performing rsync

# do the rsync thing
rsync -v -a --delete --exclude-from=${HOME}/.backup/exclusions --link-dest=${dest}/backup.1 ${source}/ ${dest}/backup.0

# detach the image if necessary
if [ $useDiskImage -eq 1 ]; then
    echo Detaching mount
    hdiutil detach $dest
fi

1 Comment »

  1. So, once again, you have replaced yourself with a small shell script?

    Comment by MattyT — November 15, 2009 @ 6:11 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment