Yet another incremental rsync backup

After using rdiff-backup for about 6 months as a home files backup, I realized it’s a little bit overkill for me. I knew rsync likely versatile enough for my backups, but all I was familiar were just rsync -avz ....

After thorough reading of man rsync, I end up with the following backup scheme:

  1. make the very first backup: this is just old rsync -a ...
  2. subsequent backups should be incremental; i.e. they should contain only files which differ from their previously backed up versions (or was created/deleted)
  3. each backup should be in its own directory, which should be browseable w/o any additional tools (remember rdiff-backup’s --list-at-time option)

Here’s how it works: recent rsync versions have a smart --link-dest=DIR option. It works like this (with reference to my case): point it to directory with previous backup, so rsync will look this directory before copying file from backup source – if there’s a file identical to one being copied; if such file is found, no real copying is made, instead file from old backup is hardlinked to new backup directory.

So we end up with two backup dirs with unchanged files stored only once and being hardlinked between this backup directories.

All we have to do now is write some simple wrapper script to rotate backup directories, taking the most recent one into account while creating new backup.

Here’s my approach (not very smart, but it ‘just works’ for me):

#!/bin/bash
set -eu
RSYNC_OPTS="-a -x -H --delete-during --stats -hh -F --max-size=2G"
MOUNTPOINT=/media/portable
BACKUPDIR=$MOUNTPOINT/backup
TODAY=$(date +%Y-%m-%d)
LOGFILE=/tmp/backup.log

mountpoint -q $MOUNTPOINT || { echo $MOUNTPOINT is not a mountpoint ; exit 1; }

[ -d $BACKUPDIR ] || { echo $BACKUPDIR not found ; exit 1; }

if [ ! -L $BACKUPDIR/latest ]
then
    # first backup
    echo no previous backup, initial run
    rsync $RSYNC_OPTS $HOME/ $BACKUPDIR/backup-$TODAY \
    && ln -s backup-$TODAY $BACKUPDIR/latest
else
    # previous backup exists
    echo previous backup exists, using it
    rsync $RSYNC_OPTS --log-file=$LOGFILE --link-dest=$BACKUPDIR/latest $HOME/ $BACKUPDIR/backup-$TODAY \
    && rm $BACKUPDIR/latest && ln -s backup-$TODAY $BACKUPDIR/latest
    echo see logfile: $LOGFILE
fi

echo latest backup now is:
readlink -e $BACKUPDIR/latest

I backup my laptop homedir once a week to an external usb-drive mounted to /media/portable as you may notice. For now I have directories like these: latest (this is link to the latest backup), backup-2008-05-25, backup-2008-05-18, backup-2008-05-11


P.S.: I’ve found a nice program, which uses the same approach as described above: mrb, it is based on GNU make and rsync and can be installed on Ubuntu or Debian with sudo apt-get install mrb.