2008-06-09

Rotated backup

Years ago I 'invented' a wheel, I mean rotated backup scheme. My idea was to store three types of copies:

  • Monthly, stored for ever

  • Weekly, overwrote every month (a copy for every 1st, 2nd, 3rd, 4th and sometimes 5th Friday of the month

  • Daily, overwrote every week (a copy for every weekday)


This schema provides 5 (7 including weekends) last copies, and 5 weekend copies (last month) and a copy from the beginning of every month. The advantage is that I can preserve some space and still have quite good resource of files from the past. The disadvantage is that I can't restore file file created 10 days ago and deleted 9 days ago (if it wasn't Friday :-)).

Usage:
/usr/local/bin/rotated_backup.sh server directory
invoked from backup server assuming that directory fo copies is called /var/BACKUP. How its moved on a tape or DVD is another story.

If you prefer to follow symbolic links, add 'h' to tar command.


#!/bin/bash

. /usr/local/bin/password
LC_ALL=C
DATE=`date +%F`
DAYOFMONTH=`date +%d`
DAYOFMONTH=${DAYOFMONTH#0}
DAYOFWEEK=`date +%a`
let WEEKOFMONTH=$DAYOFMONTH/7+1
MONTH=`date +%m`

LOCALSTORAGE=/var/BACKUP
SERVER=$1
DIRTOBACKUP=$2
DIRNAME=${DIRTOBACKUP##*/}
PARENTDIR=${DIRTOBACKUP%/*}

# Don't write undescore if its root subdirectory
# (PARENTDIR is /, means empty)
if [[ "$PARENTDIR" != "" ]]
then
PARENTDIR="${PARENTDIR##*/}_"
else
PARENTDIR="root_"
fi

if [[ "$DIRNAME" != "" ]]
then
DIRNAME="${DIRNAME##*/}_"
fi

DAILYARCHNAME=${LOCALSTORAGE}/${SERVER}_${PARENTDIR}${DIRNAME}${DAYOFWEEK}.tgz
WEEKLYARCHNAME=${LOCALSTORAGE}/${SERVER}_${PARENTDIR}${DIRNAME}WEEK_${WEEKOFMONTH}.tgz
MONTHLYARCHNAME=${LOCALSTORAGE}/${SERVER}_${PARENTDIR}${DIRNAME}MONTH_${MONTH}_${DATE}.tgz

# Check argument list. Two are required.
: ${2?"Usage: $0 servername dir_to_backup"}

# Check the order of arguments (no slashes in servers name,
# at least one slach in directory name)
if [[ "$SERVER" == *"/"* ]]
then
echo "The first argument is a server and can't contain slashes."
exit 1
fi

if [[ "$DIRTOBACKUP" != "/"* ]]
then
echo "The second argument is a directory and must contain at least one slashe, the leading one."
exit 1
fi

# ==== FUNCTIONS ====
function getbackup {
# Backup
if [[ -e $1 ]]
then
mv $1 ${1}_old
fi
# PASS is in /usr/local/bin/password
# sourced at the beginning of the script
ssh $SERVER tar zc $DIRTOBACKUP | openssl des3 -salt -k $PASS > $1

# Error checking
if [[ -e $1 ]]
then
if [[ -s $1 ]]
then
echo "Back up is OK (${1})"
rm -f ${1}_old
else
echo "Back up failed. File is epmty (${1})"
mv ${1}_old $1
exit 2
fi
else
echo "Backup failed. File not created (${1})"
mv ${1}_old $1
exit 3
fi
}

# ==== EXECUTION ====
if [ "$DAYOFMONTH" == "01" ]; then
echo "Monthly backup"
getbackup $MONTHLYARCHNAME
elif [ "$DAYOFWEEK" == "Fri" ]; then
echo "Weekly backup"
getbackup $WEEKLYARCHNAME
else
echo "Daily backup"
getbackup $DAILYARCHNAME
fi

exit 0


Incremental backup


If you have really huge amount of data to copy, its good to short daily backup and copy only changed files. There are some limit of the technique, as it relays on timestamp, but quite effective.


ssh $SERVER tar zc --listed-incremental=/var/log/daily.snar $DIRTOBACKUP | openssl des3 -salt -k $PASS > $1


In case of using this schema, the backup function for daily and other types will be different.

  • Daily backup: take /var/log/daily.snar and start copying

  • weekly backup: delete /var/log/daily.snar and perform with new on (neccessary for Monday backup)

  • monthly backup: can simply omit this parameter. The next daily backup perform as usual - incremental to the last one.






If you have another idea about good backup schemes, or you just felt inspired to write something, leave a comment, please.

Virtual tapes for every daily, weekly and monthly copy




Timeline of rotated backup




Have you any impression about it? Do something! :-)
Leave a comment please or write me an e-mail, please.

No comments: