#!/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

