NSLU2-Linux
view · edit · print · history

HowTo.BackupScript History

Hide minor edits - Show changes to markup

June 10, 2008, at 01:02 PM by JNC --
Added line 1:

[@

Added line 432:

@]

June 10, 2008, at 01:02 PM by JNC --
Added lines 1-430:
  1. !/bin/bash
  2. #######################################
  3. Constants
  4. #######################################

ROOT_UID=0; OK=0; KO=1;

  1. source and dest directory must not end by /

BACKUP_DIRECTORY="/backup"; BACKUP_DIRECTORY_PATTERN="Backup";

BACKUP_PARTITION="/dev/sdb2";

STANDARD_CONFIG_FILE="/etc/backup"

  1. #######################################
  2. Global variables
  3. #######################################

G_BackupDirectory="Not yet assigned"; G_DatedBackupDirectory="Not yet assigned";

G_Date="Not yet assigned"; G_NbrFilesAlreadyExist=0; G_NbrDirAlreadyExist=0;

  1. #######################################
  2. _Report
  3. #######################################

function _Report {

	CurrentTime?=`/bin/date | /usr/bin/awk '{print $4}'`;
	/bin/echo "$G_Date $CurrentTime $1 : $2";

}

  1. #######################################
  2. _ReportDiskSpace
  3. #######################################

function _ReportDiskSpace {

	Message="$BACKUP_PARTITION full by ";
	Message=$Message"`/bin/df | grep $BACKUP_PARTITION | /usr/bin/awk '{print $5}'`";
	Message=$Message" (available=";
	Message=$Message"`/bin/df | grep $BACKUP_PARTITION | /usr/bin/awk '{print $4}'`";
	Message=$Message" - used =";
	Message=$Message"`/bin/df | grep $BACKUP_PARTITION | /usr/bin/awk '{print $3}'`";
	Message=$Message")";

	_Report "INFO" "$Message" ;

}

  1. #######################################
  2. _IsRootUser test function
  3. #######################################

function _IsRootUser {

	if [ `/usr/bin/id -u` -ne $ROOT_UID ]; then
	{
		return $KO;
	}
	else
	{
		return $OK;
	}
	fi;

}

  1. #######################################
  2. _UpdateGlobalVariables
  3. #######################################

function _UpdateDateGlobalVariables {

	# G_Date
	# ======
	# Year
	G_Date=`/bin/date | /usr/bin/awk '{print $6}'`;

	# Month
	case "`/bin/date | /usr/bin/awk '{print $2}'`" in
		"Jan")	G_Date="$G_Date"01;;
		"Feb")	G_Date="$G_Date"02;;
		"Mar")	G_Date="$G_Date"03;;
		"Apr")	G_Date="$G_Date"04;;
		"May")	G_Date="$G_Date"05;;
		"Jun")	G_Date="$G_Date"06;;
		"Jul")	G_Date="$G_Date"07;;
		"Aug")	G_Date="$G_Date"08;;
		"Sep")	G_Date="$G_Date"09;;
		"Oct")	G_Date="$G_Date"10;;
		"Nov")	G_Date="$G_Date"11;;
		"Dec")	G_Date="$G_Date"12;;
		*) 	_Report "ERROR"  "Improper value";
			exit;;
	esac

	# Day
	DayNumber?=`/bin/date | /usr/bin/awk '{print $3}'`;
	if [ $DayNumber -lt 10 ]; then
	{
		G_Date="$G_Date"0"$DayNumber";
	}
	else
	{
		G_Date="$G_Date$DayNumber";
	}
	fi;

}

  1. #######################################
  2. _UpdateDestinationDirectoriesGlobalVariable
  3. $1 : Backup Keyword
  4. #######################################

function _UpdateDestinationDirectoriesGlobalVariables {

	if [ -z "$1" ]; then
	{
		_Report "ERROR" "The backup keyword is empty";
		exit $KO;
	}
	else
	{
		G_BackupDirectory="$BACKUP_DIRECTORY/$BACKUP_DIRECTORY_PATTERN$1";
		G_DatedBackupDirectory="$BACKUP_DIRECTORY/$BACKUP_DIRECTORY_PATTERN$1$G_Date";
	}
	fi;

}

  1. #######################################
  2. _RecursiveHardLink
  3. $1 is the source directory to copy
  4. $2 is the destination directory
  5. #######################################

function _RecursiveHardLink {

	if [ ! -e $1 ]; then
	{
		_Report "WARNING" "Source directory $1 does not exist"; # can happen if run for the very first time
		return $KO;
	}
	elif [ -f $1 ]; then
	{
		_Report "ERROR" "Source directory $1 is a file";
		exit $KO;
	}
	fi;

	if [ -e "$2" ]; then
	{
		if [ -d "$2" ]; then
		{
			let "G_NbrDirAlreadyExist=$G_NbrDirAlreadyExist+1";
		}
		else
		{
			_Report "ERROR" "$2 already exists and is a file";
			exit $KO;
		}
		fi;
	}
	else	
	{
		/bin/mkdir "$2";
	}
	fi;

	IFS=$'\n';
	for inode in $(ls $1); do

		if [ -f "$1/$inode" ]; then
		{
			if [ -e "$2/$inode" ]; then
			{
				if [ -d "$2/$inode" ]; then
				{
					_Report "ERROR" "$2/$inode already exists and is a directory";
					exit $KO;
				}
				else
				{
					let "G_NbrFilesAlreadyExist=$G_NbrFilesAlreadyExist+1";
				}
				fi;
			}
			else
			{
				/bin/ln "$1/$inode" "$2/$inode";
			}
			fi;
		}
		elif [ -d "$1/$inode" ]; then
		{
			_RecursiveHardLink "$1/$inode" "$2/$inode";
		}
		fi;
	done

}

  1. #######################################
  2. _Backup
  3. $1 is the source directory to backup
  4. $2 is the destination backup directory
  5. #######################################

function _Backup {

	# test parameters
	# ---------------
	if [ ! -e "$1" ]; then
	{
		_Report "ERROR" "The source directory to backup $1 does not exist";
		exit $KO;
	}
	elif [ -f "$1" ]; then
	{
		_Report "ERROR" "The source directory to backup $1 is a file";
		exit $KO;
	}
	fi;

	if [ ! -e "$2" ]; then
	{
		_Report "WARNING" "The backup directory $2 does not exist";
		/bin/mkdir "$2";
		_Report "INFO" "Directory $2 created";
	}
	elif [ -f "$2" ]; then
	{
		_Report "ERROR" "The backup directory $2 is a file";
		exit $KO;
	}
	fi;


	# rsync the directories
	# ---------------------
	/usr/bin/rsync -v -a --delete $1/ $2/

}

  1. #######################################
  2. _DeleteDatedBackups
  3. $1 is the max number of dated backups to keep
  4. #######################################

function _DeleteDatedBackups {

	# compute the directories filter for ls
	# =====================================
	let Lgth=`expr length $G_DatedBackupDirectory`-8;
	Filter="`expr substr $G_DatedBackupDirectory 1 $Lgth`*";

	# delete all files except NbrFiles?
	# ================================
	IFS=$'\n';
	let FilesNbr?=`ls -d $Filter | wc -l`-1;
	let FilesToRemove?=`ls -d $Filter | wc -l`-$1;

	_Report "INFO" "Found $FilesNbr directories for $1 allowed"

	if [ $FilesToRemove -gt 0 ]; then
	{
		_Report "INFO" "Will remove $FilesToRemove directories"

		FilesList?="`ls -d $Filter | tail -$FilesNbr | head -$FilesToRemove`";
		for File in $FilesList; do
			_Report "INFO" "Removing $File...";
			rm -r $File;
		done
	}
	fi;

}

  1. #######################################
  2. _BackupADirectory
  3. $1 is the source directory to backup
  4. $2 is the keyword for the backup
  5. $3 indicates the max number of dated backup to keep
  6. #######################################

function _BackupADirectory {

	# check parameters
	# ================
	if [ ! -e "$1" ]; then
	{
		_Report "ERROR" "The source directory to backup $1 does not exist";
		exit $KO;
	}
	elif [ -f "$1" ]; then
	{
		_Report "ERROR" "The source directory to backup $1 is a file";
		exit $KO;
	}
	fi;

	if [ -z "$2" ]; then
	{
		_Report "ERROR" "The backup keyword is empty";
		exit $KO;
	}
	fi;

	if [ -z "$3" ]; then
	{
		_Report "ERROR" "No backup length parameter";
		exit $KO;
	}
	elif [ $3 -lt 0 ]; then
	{
		_Report "ERROR" "The backup length ($3) must be positive or nul";
		exit $KO;
	}
	fi;


	# Update directories name global variables
	# ========================================
	_UpdateDestinationDirectoriesGlobalVariables $2;

	_Report "INFO" "The source to backup is $1";
	_ReportDiskSpace;

	# delete the unnecessary dated backups
	# ====================================
	_DeleteDatedBackups $3


	# Hard links creation
	# ===================
	if [ $3 -gt 0 ]; then
	{
		_Report "INFO" "The dated backup directory is $G_DatedBackupDirectory";
		_Report "INFO" "Dated backup in progress...";
		G_NbrFilesAlreadyExist=0;
		G_NbrDirAlreadyExist=0;

		_RecursiveHardLink $G_BackupDirectory $G_DatedBackupDirectory;

		if [ $G_NbrFilesAlreadyExist -gt 0 -o $G_NbrDirAlreadyExist -gt 0 ]; then
		{
			_Report "WARNING" "$G_NbrFilesAlreadyExist files and $G_NbrDirAlreadyExist directories were already existing : those files have not been overwritten";
		}	
		fi;

		_Report "INFO" "Dated backup completed...";
		_ReportDiskSpace;
	}
	else
	{
	_Report "INFO" "No dated backup as requested"
	}
	fi;


	# start the backup
	# ================
	_Report "INFO" "The current backup directory is $G_BackupDirectory";
	_Report "INFO" "Backup in progress...";
	_Backup $1 $G_BackupDirectory;
	_Report "INFO" "Backup completed...";
	_ReportDiskSpace;

}

  1. #######################################
  2. _ScheduleBackupsFromFile
  3. $1 is the config file name
  4. #######################################

function _ScheduleBackupsFromFile {

	# test if the file exists
	# -----------------------
	if [ ! -e $1 ]; then
	{
		_Report "ERROR" "The config file $1 does not exist";
		exit $KO;
	}
	elif [ ! -f $1 ]; then
	{
		_Report "ERROR" "$1 is not a file";
		exit $KO;
	}
	fi;

	# read the file and run the backup
	# --------------------------------
	IFS="	";  # tab
	cat $1 | while read SourceDir? Keyword MaxDatedBackups?; do 
		_BackupADirectory $SourceDir $Keyword $MaxDatedBackups;
		IFS="	"; # tab, overwritten by _RecursiveHardLinks
	done

}

  1. #######################################
  2. _DisplaySyntax
  3. #######################################

function _DisplaySyntax {

	_Report "" "Syntax : $0";
	_Report "" "1 argument  -> use this argument as a config file";
	_Report "" "3 arguments -> source directory to backup";
	_Report "" "            -> backup keyword";
	_Report "" "            -> backup length (can be 0 or more)";

}

  1. #######################################
  2. Main script
  3. can be used with 1 parameter (config file name)
  4. or with 3 parameters (source directory, backup keyword, backup length)
  5. #######################################
  6. Update global var
  7. =================

_UpdateDateGlobalVariables;

  1. initial tests
  2. =============
  3. make sure we are root

if ( ! _IsRootUser ); then {

	_Report "ERROR" "Must be root to use the script";
	exit;

} fi;

  1. test parameters
  2. ===============

case $# in 1) _ScheduleBackupsFromFile $1;; 3) _BackupADirectory $1 $2 $3;;

  • ) _DisplaySyntax;;

esac

view · edit · print · history · Last edited by JNC.
Originally by JNC.
Page last modified on June 10, 2008, at 01:02 PM