#!/bin/bash #-xf
# Backup Strategy version 2.00 made by Marian Boricean, July 2008
# Last update March 2009
#
# This script will make (apparent) full backups of a given list of folders
# for a specified number of days using 'rsync' tool.
# This script gets as the first argument the frequency of the backup
# The frequency can be: hourly, daily, weekly, monthly, yearly
# The script will manage four consecutive backups (.latest, .0, .1, .2)
#
# ------Variables---------

SDIR="/home/director1/ /etc/ /home/director3/" # List of directories to backup separated by spaces
DDIR="/media/EXTERNAL/director2/"               # Where to do the backup. Please use a different phisical disk.
LOG=~/tmp/backup.log
PID=~/tmp/backup.pid
ADMIN=me@mydomain.com
EXCLUDFILE="/etc/backup-excludes.txt"
RSYNC='/usr/bin/rsync -avhH --progress'
DATEFORMAT="%F_%H.%M"
BSTIME=$(date +"$DATEFORMAT")
# ------Here is where it ends your modifications ------------------------------------
# ------Do not modify what is bellow, unless you want to improve the script ---------
#
# ------Functions--------------------------------------------------------------------
error () {
        echo "$0: $@" 1>&2 |tee -a $LOG
        exit 1
}
MOVE () {
# Make sure you run as root
#       if [ `id -u` != 0 ]; then error "You must run this as root"; fi 
# Swift the backups and create the latest folder
        if [ -d $DDIR/$1.2 ]; then
                rm -rf $DDIR/$1.2
        fi
        if [ -d $DDIR/$1.1 ]; then
                mv $DDIR/$1.1 $DDIR/$1.2
        fi
        if [ -d $DDIR/$1.0 ]; then
                mv $DDIR/$1.0 $DDIR/$1.1
        fi
        if [ -d $DDIR/$1.latest ]; then
                mv $DDIR/$1.latest $DDIR/$1.0
                mkdir $DDIR/$1.latest
        fi
}
BACKUP () {  # it can take the following arguments: hourly, daily, weekly, monthly or yearly
        # Remove the log file
        rm -f $LOG.$1
        # Create the log file anew
        touch $LOG.$1
        # Check if it's an hourly backup
        if [ $1 = "hourly" ] ; then
                #Send to the log the start time
                echo "$1 backup ran $(date +"$DATEFORMAT")" >> $LOG.$1
                # Rename the folders from .latest to .0 to .1 to .2 (first delete existing .2)
                MOVE $1
                # Create an empty file with the start time in the destination directory
                touch $DDIR/$1.latest/---Start-$BSTIME---
                # For every folder to backup, perform the rsync, linking to the previous backup.
                for sdir in $SDIR; do
                        $RSYNC  --exclude-from $EXCLUDFILE  --link-dest=$DDIR/$1.0 $sdir $DDIR/$1.latest/ 2>&1 | tee -a $LOG.$1
                done
                # Backup finished, create an empty file with the end time.
                touch $DDIR/$1.latest/--Finish-$(date +"$DATEFORMAT")---
                # Copy the log file to the destination folder.
                cp $LOG.$1 $DDIR/$1.latest/Backup-log.txt
                # Send email to the admin
                echo "Check the log file: file://$DDIR/$1.latest/Backup-log.txt" | mail -s "$1 Backup $(hostname)" $ADMIN
        else
        # It's not an hourly backup; therefore link to the latest one found
                echo "$1 backup ran $(date +"$DATEFORMAT" )" >> $LOG.$1
                # Does the hourly backup exist? if yes, link to it.
                if [ -d $DDIR/hourly.latest ] ; then
                        echo "The hourly backup exists; this will be the start point for the $1 backup" | tee -a $LOG.$1
                        MOVE $1
                        touch $DDIR/$1.latest/---Start-$BSTIME---
                        for sdir in $SDIR; do
                                $RSYNC  --exclude-from $EXCLUDFILE  --link-dest=$DDIR/hourly.latest $sdir $DDIR/$1.latest/ 2>&1 | tee -a $LOG.$1
                        done
                        touch $DDIR/$1.latest/--Finish-$(date +"$DATEFORMAT")---
                        cp $LOG.$1 $DDIR/$1.latest/Backup-log.txt
                        echo "Check the log file: file://$DDIR/$1.latest/Backup-log.txt" | mail -s "$1 Backup $(hostname)" $ADMIN
                else
                        # Does the daily backup exist? if yes, link to it.
                        if [ -d $DDIR/daily.latest ] ; then
                                echo "The daily backup exists; this will be the start point for the $1 backup" | tee -a $LOG.$1
                                MOVE $1
                                touch $DDIR/$1.latest/---Start-$BSTIME---
                                for sdir in $SDIR; do
                                        $RSYNC  --exclude-from $EXCLUDFILE  --link-dest=$DDIR/daily.latest $sdir $DDIR/$1.latest/ 2>&1 | tee -a $LOG.$1
                                done
                                touch $DDIR/$1.latest/--Finish-$(date +"$DATEFORMAT")---
                                cp $LOG.$1 $DDIR/$1.latest/Backup-log.txt
                                echo "Check the log file: file://$DDIR/$1.latest/Backup-log.txt" | mail -s "$1 Backup $(hostname)" $ADMIN
                        else
                                # Does the weekly backup exist? if yes, link to it.
                                if [ -d $DDIR/weekly.latest ] ; then
                                        echo "The weekly backup exists; this will be the start point for the $1 backup" | tee -a $LOG.$1
                                        MOVE $1
                                        touch $DDIR/$1.latest/---Start-$BSTIME---
                                        for sdir in $SDIR; do
                                                $RSYNC  --exclude-from $EXCLUDFILE  --link-dest=$DDIR/weekly.latest $sdir $DDIR/$1.latest/ 2>&1 | tee -a $LOG.$1
                                        done
                                        touch $DDIR/$1.latest/--Finish-$(date +"$DATEFORMAT")---
                                        cp $LOG.$1 $DDIR/$1.latest/Backup-log.txt
                                        echo "Check the log file: file://$DDIR/$1.latest/Backup-log.txt" | mail -s "$1 Backup $(hostname)" $ADMIN
                                else
                                        # Does the monthly backup exist? if yes, link to it.
                                        if [ -d $DDIR/monthly.latest ] ; then
                                                echo "The monthly backup exists; this will be the start point for the $1 backup" | tee -a $LOG.$1
                                                MOVE $1
                                                touch $DDIR/$1.latest/---Start-$BSTIME---
                                                for sdir in $SDIR; do
                                                        $RSYNC  --exclude-from $EXCLUDFILE  --link-dest=$DDIR/monthly.latest $sdir $DDIR/$1.latest/ 2>&1 | tee -a $LOG.$1
                                                done
                                                touch $DDIR/$1.latest/--Finish-$(date +"$DATEFORMAT")---
                                                cp $LOG.$1 $DDIR/$1.latest/Backup-log.txt
                                                echo "Check the log file: file://$DDIR/$1.latest/Backup-log.txt" | mail -s "$1 Backup $(hostname)" $ADMIN
                                        else
                                                # There is no latest backup available. Start from scratch!
                                                echo "the latest backup doen't exist. Strting from scratch for $1 backup"| tee -a $LOG.$1
                                                MOVE $1
                                                touch $DDIR/$1.latest/---Start-$BSTIME---
                                                for sdir in $SDIR; do
                                                        $RSYNC  --exclude-from $EXCLUDFILE  --link-dest=$DDIR/$1.0 $sdir $DDIR/$1.latest/ 2>&1 | tee -a $LOG.$1
                                                done
                                                touch $DDIR/$1.latest/--Finish-$(date +"$DATEFORMAT")---
                                                cp $LOG.$1 $DDIR/$1.latest/Backup-log.txt
                                                echo "Check the log file: file://$DDIR/$1.latest/Backup-log.txt" | mail -s "$1 Backup $(hostname)" $ADMIN
                                        fi
                                fi
                        fi
                fi
        fi
}
# here is the actual backup 
# If you don't specify one of the valid variants, complain and exit.
# It MUST be one of the following: hourly, daily, weekly, monthly or yearly
# first verify if a backup is on-going. If it is, send an email about it and exit.

ps -fe | grep -i backup | grep -v grep | grep rsync > $PID
if [ -s $PID ] ; then
        cat $PID | mail -s "$1 backup cannot run. A backup is already in progress" $ADMIN
        echo "$1 backup cannot run. A backup is already in progress" 
        exit 1
else
        # There is not backup in progress. Now check if the destination directory exists.
        if [ -d $DDIR ] ; then
                case $1 in
                        hourly) BACKUP hourly;;
                        daily) BACKUP daily;;
                        weekly) BACKUP weekly;;
                        monthly) BACKUP monthly;;
                        yearly) BACKUP yearly;;
                        *) echo $1 "is not a valid frequency. You must specify either hourly, daily, monthly or yearly like so "
                                echo "backup.sh hourly"
                                echo "or:" 
                                echo "backup.sh monthly"; exit 1 ;;
                esac
        else
                echo "$1 backup cannot run. Destination directory doesn't exist" 
                echo "$1 backup cannot run. Destination directory doesn't exist" | mail -s "$1 backup cannot run" $ADMIN
                exit 1
        fi
fi