there is no place like ~

A small backup script

I have been using flexbackup for some time, but I always wanted a simpler and at the same time more flexible solution. After discovering the -g (alias --listed-incremental) option of tar, I decided to write my own wrapper script around tar.

Update 20 October 2014: Recently I came across obnam, which is a very neat backup program for Linux. I am now using to back up my personal data and can wholeheartedly recommend it.

Description

The resulting script can generate full and incremental backups (-i option). Also, it allows to backup some configurations or all configurations with the -a option. A configuration is a name for a set of files to back up. The list of all configurations can be printed with the -l option.

Most of the script is option parsing and validation. The bulk of the job is done by the taritup() function. This function takes as the first argument the name of the use supplied configuration in the command loop and as the second the name of the config. If both names match (or the -a option was set) then the script starts tarring up the file. The script assumes all paths are relative paths starting from the root directory.

The loop at the end of the script just loops through all given configurations and calls taritup() for each of them.

#!/bin/sh
set -e

dest=/media/data/backup
timestamp=`date +%Y-%m-%dT%H%M%S`

usage() {
    echo "$0: [OPTIONS] [CONFIG...]"
}

help() {
    usage
    echo
    echo "OPTIONS"
    echo "    -a        backup all configurations."
    echo "    -h        print this help message."
    echo "    -i        do an incremental backup."
    echo "    -l        list all configs and exit."
    echo "    -v        verbose mode: print the files to stdout."
}

type="f"
all="n"
verbose=""
list="n"
while getopts ahilv opt; do
    case "$opt" in
        a)  all="y";;
        h)  help
            exit 0;;
        i)  type="i";;
        l)  list="y"; all="y";;
        v)  verbose="v";;
        \?)     # unknown flag
            usage >&2
            exit 1;;
    esac
done
shift `expr $OPTIND - 1`

if [ ! -d "$dest" ]; then
    echo >&2 "$0: directory $dest does not exist."
    exit 1
fi
if [ "$all" = "y" ]; then
    set "x"
fi


taritup() {
    conf="$1"
    name="$2"
    shift 2

    if [ "$list" = "y" ]; then
        echo "$name"
        return
    fi
    if [ "$conf" = "$name" -o "$all" = "y" ]; then
        snarfile="$dest/$name.snar"
        backupfile="$dest/$name-$timestamp.$type.tar.xz"
        if [ "$type" = "f" ]; then
            rm -f -- "$snarfile"
        fi
        tar -c"$verbose" -C"/" -g"$snarfile" -J -f"$backupfile" "$@"
    fi
}

for conf in "$@"; do
    taritup "$conf" "etc" etc
    taritup "$conf" "home-fred" home/fred
    taritup "$conf" "var-www-site1" var/www/site1
    taritup "$conf" "var-www-site2" var/www/site2
done