Roland's homepage

My random knot in the Web

Automated local backups

These days it is commonplace to have hardware or software RAID1, even in common PCs. In previous machines I’ve used ataraid to implement RAID1.

The advantage is that every write is recorded on two disks at once, minimizing the chance of data loss. The flip side of the coin is that stupid mistakes are also immediately replicated!

So what I wanted was really a combination of:

  • A recent automated backup. Recent because backups are better when they are fresh and automated because then I don’t have to think about it every day.
  • A way to fix stupid mistakes for a limited time. Mostly this concerns accidental deletion or modification of files where I realize quite quickly that I shouldn’t have done that.

The following is what I’ve come up with; There are two identical disks in my machine. One is the primary disk that is in daily use. The second one has partitions of the same size as those on the first disk. Started by cron(8) when I’m sleeping, the following shell-script mounts the relevant partitions and then uses rsync to syncronize the partition on the second to that on the first disk. After synchronizing, it unmounts the partition in question.

#!/bin/sh
# -*- shell-script -*-
#
# This should be: /usr/local/sbin/backup-local
# Back up local filesystems from ada0 to ada1 on Slackbox.
#
# Author: R.F. Smith <rsmith@xs4all.nl>
# $Date: 2012-08-31 21:21:38 +0200 $
#
# To the extent possible under law, Roland Smith has waived all copyright and
# related or neighboring rights to backup-local. This work is published from the
# Netherlands. See https://creativecommons.org/publicdomain/zero/1.0/

# Check for non-standard programs that are used in this script.
PROGS="rsync"
for P in $PROGS; do
    which $P >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        echo "$(basename $0): The program \"$P\" cannot be found."
        exit 1
    fi
done

FLAGS="-axq -H --delete --force-change"
LOG="logger -t 'backup-local'"

# This script assumes that the backups are not mounted.

mount /mnt/bk/root
if df|grep /mnt/bk/root >/dev/null; then
    #echo "/ is good to go!"
    rsync $FLAGS / /mnt/bk/root && $LOG "/ successfully backed-up."
    umount /mnt/bk/root
else
    echo "Backup for / not mounted! Not backed up."
fi

mount /mnt/bk/usr
if df|grep /mnt/bk/usr >/dev/null; then
    #echo "/usr is good to go!"
    # Trailing slash after source is important! See rsync(1).
    rsync $FLAGS /usr/ /mnt/bk/usr && $LOG "/usr successfully backed-up."
    umount /mnt/bk/usr
else
    echo "Backup for /usr not mounted! Not backed up."
fi

mount /mnt/bk/home
if df|grep /mnt/bk/home >/dev/null; then
    #echo "/home is good to go!"
    rsync $FLAGS /home/ /mnt/bk/home && $LOG "/home successfully backed-up."
    umount /mnt/bk/home
else
    echo "Backup for /home not mounted! Not backed up."
fi

mount /mnt/bk/var
if df|grep /mnt/bk/var >/dev/null; then
    #echo "/var is good to go!"
    rsync $FLAGS /var/ /mnt/bk/var && $LOG "/var successfully backed-up."
        umount /mnt/bk/var
else
    echo "Backup for /var not mounted! Not backed up."
fi

If the backups are succesful, this will show up in /var/log/messages. If commands fail, cron is set up to mail the errors to to me.

This setup has haved my data on several occasions; first a total disk failure, second a accidental deletion of an important shared libary rendering the system unusable and third a dying disk. I was very careful when restoring the files (mounting the backups read-only), but I was up and running again much faster than when I would have had an off-line backup. Not to mention that this local backup is always at most a day old.


←  Updating multiple systems using a pre-built FreeBSD Switching IPython to Python 3  →