Source

simple-tarsnap / simple-tarsnap.sh

#!/bin/bash
# vim:ts=4:sw=4:expandtab:cindent

# Copyright (c) 2009, Mads Sulau Joergensen <mads@sulau.dk>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the <organization> nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Mads Sulau Joergensen ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Mads Sulau Joergensen BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Newest version is always found at: http://bitbucket.org/madssj/simple-tarsnap/
#
# Will make a backup using tarsnap, where it will make 7 daily backups, which are
# then concanated into a weekly backup once a week, which are then concanated into
# a monthly backup once a month. That means, that you will loose the resolotion of
# the backups stored in tarsnap over time. You can overwrite this behaviour by
# passing the -d flag to simple-tarsnap.sh, which will force it always to make
# a daily backup. That way it will never delete a tarsnap archive.
#
# Examples:
#
# Creating a backup of / leaving the concanation to simple-tarsnap.sh with a
# random 3600 second sleep interval.
# @daily /path/to/simple-tarsnap.sh -s 3600 -b full-backup /

# default options
backup_name="backup"
max_sleep=7200
dryrun=0
quiet=0
autocleanup=1
type="auto"

function usage {
    cat >&2 << EOF
Usage: $0 [options] extra args to tarsnap ...

Params:
-h   This message
-n   Just show what commands would be run (dry run)
-q   Quiet
-b <name>   Basename of the backup (default backup)
-s <seconds>   Maximum interval to sleep before starting backup
               set to 0 to disable sleeping (default 7200)
Controlling backup types and automatic deletion of archives:
-d   Force daily backup
-w   Force weekly backup
-m   Force monthly backup
-A   Disable auto cleanup, useful with a write only key

The archives produced follows the following naming schema:
<basename>-<daily|weekly|monthly>-<date Y-m-d>. So if a daily backup
named home is produced on the first of january, it will be in a
archive named home-daily-2009-01-01.

Examples:
Create a backup of /home with a basename of home-backup.
$0 -s 0 -b home-backup /home

When having to pass an argument that $0 uses to tarsnap, seperate
arguments with a double dash (--) as so:
$0 -s 0 -b home-backup -q -- -q /home
EOF
    exit 1
}

# read options from command line
while getopts Ahndqwms:b: o
do  case "$o" in
    n)  dryrun=1;;
    q)  quiet=1;;
    s)  max_sleep="$OPTARG";;
    b)  backup_name="$OPTARG";;
    d)  type="daily";;
    w)  type="weekly";;
    m)  type="monthly";;
    A)  autocleanup=0;;
    h|[?])
        usage;;
    esac
done
shift $(($OPTIND-1))

tarsnap_args="$@"

# autodetect backup type
if [ $type == "auto" ]
then
    type="daily"
    if [ "`date +%d`" == "1" ]
    then
        type="monthly"
    elif [ "`date +%w`" == "0" ]
    then
        type="weekly"
    fi
fi

function do_log {
    [ $quiet -eq 0 ] && echo "`date +%F` $*"
}

function do_tarsnap {
    cmd=""
    if [ $dryrun -gt 0 ]; then
        cmd="echo $cmd"
    fi
    cmd="$cmd tarsnap $*"
    $cmd
}

function do_cleanup {
    case $1 in
        weekly) marked_archives="daily";;
        monthly) marked_archives="weekly";;
    esac


    if [ -n "${marked_archives}" ]
    then
        for archive in `do_tarsnap --list-archives | grep "^${backup_name}-${marked_archives}"`
        do
            do_log "deleting archive $archive"
            do_tarsnap -d -f $archive
        done
    fi
}

if [ $max_sleep -gt 0 ]
then
    do_log "sleeping ..."
    sleep $(($RANDOM % $max_sleep))
fi

archive_name="${backup_name}-${type}-`date +%Y-%m-%d`"

do_log "doing backup of $archive_name with args '${tarsnap_args}'"

do_tarsnap -c -f $archive_name $tarsnap_args

if [ $? == 0 ]
then
    if [ $autocleanup == 1 ]
    then
        do_log "cleaning up"

        do_cleanup $type
    fi

    do_log "done"
else
    do_log "tarsnap backup finished with errors, not cleaning up"
fi