Backup Bash Script

This bash script is designed to backup the filesystems here at PyeNet. This script was developed to surround and manipulate the DAR (Disk ARchive) utility as needed for the filesystems.

Version 3 of this script has been developed to include a rotation schedule.

Version 4 introduced the ability to copy the back files using the openSSH scp utility.

DAR is designed to backup filesystems to disk or CD/DVD media. For more details, and downloading, visit the home page of DAR. However check your distribution's installable software to see if they have included a version of DAR.

Features and Overview

Features of this bash script are:

  • Uses a configuration file to specifiy options, so the script itself does not need to change* between machines.
  • Backup files are created on a local destination directory then copied to a remote distination**.
  • Can create seperate new backup files each time the script runs, or overwrite the previous backup file.
  • Creates a log file that indicates what happened during the backup, and what didn't happen if things didn't work.
  • The script can email the logfile. This feature uses a PERL script to do this, details below.
  • * There maybe a requirement to change some variables that point to the location of executables, these are commented in the script.
  • ** For best fault tolerance the local destination should be a separate hard disk in the machine, but does not need to be.

Basic overview of what the script does:

  • Reads the configuration file to setup the variables required for the rest of the script.
  • Confirms that the filesystems mentioned in the configuration are mounted.
  • Checks the free disk space and the size of the data to be backed up and compares them.
  • Starts the backup of the data to the local destination.
  • Copies the backup files from the local destination to the remote destination.
  • Emails the logfile to the account specified in the configuration.
  • If there is an error in any of the above steps the logfile is updated with a possible cause and then emailed.

Requirements:

Installation

Install the DAR utiltiy as per the current instructions. Note that this script is using the compression feature of DAR so if you do compile from the sources make sure that this option is compiled in.

Once the utility is installed check the location of the dar binary using the command whereis dar and confirm that this is correct in the appropriate line in the script.

Install the sendEmail script as per it's README file. Basically as root copy the file to the /usr/local/bin directory. Set the file as executable and it is ready to go (assuming you have a recent version of PERL installed).

Logged back in as a non-root user and running the sendEmail command should produce a listing of the options required to correctly run sendEmail. This confirms it is installed correctly.

Run the command whereis sendEmail to confirm the location and check this is correct in the script.

Copy the example configuration file to a filename that indicates the data being backed up. As explained in the comments within the configuration file, the name given to the file is also the base name used for the backup files once things get underway.

Go through each configuration line changing it as needed by your backup requirements. Each option is documented in the configuration file itself.

To run the backup from the command line the following syntax is used ./do_backup  <config_filename>. It is suggested to set up a configuration file that backs up a test directory first. Once this is working change it to backup a real one.

Once this is all completed adding an entry to the root users CRONTAB will make sure that the backup is performed on a regular basis.

Things I would like to add:

  • More comprehensive reporting from the DAR utility so these could be included in the logfile.
  • Add a backup rotation system to make sure that my disk space on the destination directories is not filled.

Cheers Jim

Disclaimer - Please note that this system is working well on my servers and configuration. I can not be responsible for it working, or not working, on your configuration as I do not know what your configuration is. However if you do find any issues please let me know so I can find a solution to them.

Note that even though the lines below flow off the edge of the page they will copy and paste into an editor AOK.

#!/bin/sh
################################################################################
# do_backup
#
# A BASH script backup routine using DAR
#
# This script will backup the directories specified to a local disk and then
# copy the backup files to a remote mounted location
#
# (C) 2005, 2006 Jim Pye - PyeNet Universal
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
#
# Invocation: do_backup configuration_file
#
# Version History:
# Version 1, Feb 2005
# Using my original backup script as a starting point
# Backs up files to the local mirrored data volume on local machine
# then copies the files to a remote server's volume
#
# Version 2, Dec 2005
# - Modified to make more variables to make modifications of script easier
# - Also added the loop thru the SRC_DIRS array to make the script more compact
# - Added the Directory space checks
# - Added the ability to control whether the backup creates subdirs for each
# backup or not
# - Moved the variables to seperate configuration file to allow for an even
# more generic script
#
#
# TODOs
#
# - Need to output the error message returned by each command to the logfile
# to aid in troubleshooting
#
# - Need to add backup rotation mechanism
#
###############################################################################

# Script Begins...
#
# Setup variables to use later on
#
# Utilities used in script
# The full path is required to the utility commands as this script is intended
# to be run under a CRON job
# The location of each of these utilities needs to be confirmed before running
# script
#
DATE=/bin/date
TAIL=/usr/bin/tail
CUT=/usr/bin/cut
MOUNT=/bin/mount
GREP=/bin/grep
DF=/bin/df
DU=/usr/bin/du
MKDIR=/bin/mkdir
CP=/bin/cp
GAWK=/bin/gawk
#
# The following definitely need to be confirmed as they are not standard
# utilities
#
DAR=/usr/local/bin/dar
SENDEMAIL=/usr/local/bin/sendEmail

#
# Check to see if configuration file specified on command line.
# If so use it to populate variables needed for script, if not error out...
#
# The name used for the configuration file is also used to specify the name of
# the backup being performed. This name is used as the base for the
# directories and filename of the backup
if [ -z "$1" ]; then
echo "do_backup: Oops, you forgot to specify the configuration file I am to use"
exit 1
else
if [ ! -f "$1" ] || [ ! -r "$1" ]; then
echo "do_backup: There is a problem accessing the file: $1"
echo " Please make sure this file exists and is readable"
exit 1
else
BACKUP_FULL_NAME="$1"
. "$1"
fi
fi

# The following function is designed to make the entries in the logfiles
# easier to read.
# It takes a number, the bytes free or used, and inserts separators for every
# 1000
# See http://www.pyenet.co.nz/develop/thou-separator.html for a standalone
# version of this function.
function thou_sep
{
THOU_SEP=","
# Declare Display Number as a string equal to number the function is called with
declare +i DISP_NUM=$1
# Find the length of the Display Number variable
declare -i LGTH_DISP_NUM=${#DISP_NUM}
# Set up a variable to contain the part of the string being worked on and the
# thousands separator
SEP_NUM=""
# Loop thru cutting the number string into 3 character chunks and add the
# thousands separator
until [ $(($LGTH_DISP_NUM < 3)) = 1 ] ; do
CURRENT_PART=${DISP_NUM:$LGTH_DISP_NUM-3}
DISP_NUM=${DISP_NUM%$CURRENT_PART}
SEP_NUM="$THOU_SEP$CURRENT_PART$SEP_NUM"
LGTH_DISP_NUM=$(($LGTH_DISP_NUM - 3))
done
# Add the last chunk to the beginning of the number to be displayed
DISP_NUM=$DISP_NUM$SEP_NUM
# However if the number of digits in the number entered is divisible by 3 it
# will have a leading thousands separator, this will remove it
DISP_NUM=${DISP_NUM#$THOU_SEP}
# Display the separated number
echo "$DISP_NUM"
}

# Strip off the path to get the name of this backup from the filename of the
# configuration file used.
BACKUP_NAME=${BACKUP_FULL_NAME##/*/}

# Logfile Name - This is the name of log file based on the combination of the
# directory specified in the configuration file, the name of the backup and
# the string -backup.log
LOGFILE_LOC="$LOGFILE_DIR/$BACKUP_NAME-backup.log"

# Current Date - This is used to date stamp the email and, if used, the
# directory created for the backup
CURDATE="$($DATE +%Y%m%d-%H%M)"
CURDATE_EMAIL=$CURDATE

# If the SUBDIR is empty we then empty the CURDATE variable to make it not
# appear in the paths
if [ -z "$SUBDIR" ]; then
CURDATE=""
fi

###########################################
#
# Actual backup procedure from here on...
#
###########################################

# Create a header for current backup job in the logfile, we append current job
# to log
echo " " >> $LOGFILE_LOC
echo "=*=*=*= $BACKUP_NAME backup of $LOC_SYSTEM_NAME =*=*=*=" >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC
echo -n "Started backup job at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC


# Check for and mount local mount point
echo -n "Checking for local mounted filesystem $LOC_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
if ! $GREP $LOC_MOUNT_POINT /etc/mtab
then
echo "do_backup: $LOC_MOUNT_POINT not mounted, trying to mount"
if ! $MOUNT $LOC_MOUNT_POINT
then
echo "do_backup: Failed to mount $LOC_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed to mount $LOC_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to mount $LOC_MOUNT_POINT" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi
fi
echo "do_backup: $LOC_MOUNT_POINT is mounted AOK"
echo -n " $LOC_MOUNT_POINT is mounted AOK at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC

# Check for and mount remote mount point for the copy later on. Doing this here
# to make sure operator sees login prompt. We test at end of backup to make
# sure that the remote mount point is still available before trying to copy the
# files. Note this only works from command line. If filesystem is not mounted
# during a cron job the backup will fail as no answer to password prompt can
# be given.
echo -n "Checking for remote mounted filesystem $REM_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
if ! $GREP $REM_MOUNT_POINT /etc/mtab
then
echo "do_backup: $REM_MOUNT_POINT not mounted, trying to mount"
echo " "
echo "Please enter login password for user account on $REM_SYSTEM_NAME machine"
if ! $MOUNT $REM_MOUNT_POINT
then
echo "do_backup: Failed to mount $REM_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed to mount $REM_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to mount $REM_MOUNT_POINT" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi
fi
echo "do_backup: $REM_MOUNT_POINT is mounted AOK"
echo -n " $REM_MOUNT_POINT is mounted AOK at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo -n "Finished checking mounted filesystems at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC

# Check disk space available at the destination directories
echo "do_backup: Checking backup size and free space available"
echo -n "Checking estimated backup size and free space available at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC

# Local Destination
declare -i LOC_DISK_FREE=$($DF -P -k $LOC_DEST_DIR | $TAIL -n1 | $GAWK '{ print $4 }')
declare -i REAL_LOC_DISK_FREE=$(($LOC_DISK_FREE*1024))

# If SUBDIR is empty (ie. we are not creating seperate sub directories for each
# backup) then we need to adjust the free space calculation as the old backup
# is going to be overwritten by the current one
if [ -z "$SUBDIR" ]; then
REAL_LOC_DISK_FREE=$REAL_LOC_DISK_FREE+$($DU "$LOC_DEST_DIR" -h -c -b | $TAIL -n1 | $CUT -f1)
fi
# Convert raw number into thousands separated number for display
DISPLAY_REAL_LOC_DISK_FREE=`thou_sep $REAL_LOC_DISK_FREE`

echo "do_backup: Destination $LOC_DEST_DIR has $DISPLAY_REAL_LOC_DISK_FREE bytes available"
echo -n " Destination $LOC_DEST_DIR has $DISPLAY_REAL_LOC_DISK_FREE bytes available at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC

# Remote Destination
declare -i REM_DISK_FREE=$($DF -P -k $REM_DEST_DIR | $TAIL -n1 | $GAWK '{ print $4 }')
declare -i REAL_REM_DISK_FREE=$(($REM_DISK_FREE*1024))

# If SUBDIR is empty (ie. we are not creating seperate sub directories for each
# backup) then we need to adjust the free space calculation as the old backup
# is going to be overwritten by the current one
if [ -z "$SUBDIR" ]; then
REAL_REM_DISK_FREE=$REAL_REM_DISK_FREE+$($DU "$REM_DEST_DIR" -h -c -b | $TAIL -n1 | $CUT -f1)
fi
# Convert raw number into thousands separated number for display
DISPLAY_REAL_REM_DISK_FREE=`thou_sep $REAL_REM_DISK_FREE`

echo "do_backup: Destination $REM_DEST_DIR has $DISPLAY_REAL_REM_DISK_FREE bytes available"
echo -n " Destination $REM_DEST_DIR has $DISPLAY_REAL_REM_DISK_FREE bytes available at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC

# Check the possible size of the backup dirs
declare -i TOTAL_DIR_SIZE=0
for EACH_SRC_DIR in "${SRC_DIRS[@]}"; do
declare -i DIR_SIZE=$($DU "$EACH_SRC_DIR" -h -c -b | $TAIL -n1 | $CUT -f1)
echo $EACH_SRC_DIR = $DIR_SIZE
TOTAL_DIR_SIZE=$TOTAL_DIR_SIZE+$DIR_SIZE
done

# Convert raw number into thousands separated number for display
DISPLAY_TOTAL_DIR_SIZE=`thou_sep $TOTAL_DIR_SIZE`

echo "do_backup: The estimated size of the data to backup is $DISPLAY_TOTAL_DIR_SIZE bytes"
echo -n " The estimated size of the data to backup is $DISPLAY_TOTAL_DIR_SIZE bytes at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC

# Calculate if the backup is going to fit on the destination
# Note that the calculated size of the data to be backed up is going to be
# bigger than the actual data as it does not take into account the DAR utility
# compression or the files it will not backup. But this means there should be
# plenty of spare space after backup has completed
if (( ($REAL_LOC_DISK_FREE < $TOTAL_DIR_SIZE) || ($REAL_REM_DISK_FREE < $TOTAL_DIR_SIZE) )) ; then
echo "BooHoooo not enough space left to backup files..."
echo " " >> $LOGFILE_LOC
echo -n "!!!*** WARNING ***!!! Not enough disk space to complete backup at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: No space for backup file. Estimated backup size: $DISPLAY_TOTAL_DIR_SIZE. Local space available: $DISPLAY_REAL_LOC_DISK_FREE. Remote space available: $DISPLAY_REAL_REM_DISK_FREE." -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
else
echo "Yahooo we have enough space to backup files..."
echo -n " Looks like we are good to go... at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
fi

echo "do_backup: Done checking size of backup data and free disk space"
echo -n "Done checking size of data and free disk space at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC

# Test if we are going to make seperate subdirectories for each backup if not
# test for base dir create it if it does not exist
if [ -n "$SUBDIR" ]; then
if ! $MKDIR $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE
then
echo "do_backup: Failed to create $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE on local $LOC_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed to create $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE on local $LOC_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to create $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE on local $LOC_MOUNT_POINT" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi
echo "do_backup: Created local destination dir $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE"
echo -n "Created local destination dir $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC

if ! $MKDIR $REM_DEST_DIR/$BACKUP_NAME-$CURDATE
then
echo "do_backup: Failed to create $REM_DEST_DIR/$BACKUP_NAME-$CURDATE on remote $REM_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed to create $REM_DEST_DIR/$BACKUP_NAME-$CURDATE on remote $REM_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to create $REM_DEST_DIR/$BACKUP_NAME-$CURDATE on remote $REM_MOUNT_POINT" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi
echo "do_backup: Created remote destination dir $REM_DEST_DIR/$BACKUP_NAME-$CURDATE"
echo -n "Created remote destination dir $REM_DEST_DIR/$BACKUP_NAME-$CURDATE at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC
else
# Note the - at the end is required as this is what the directory will be in
# the DAR command
if [ ! -d $LOC_DEST_DIR/$BACKUP_NAME- ]; then
if ! $MKDIR $LOC_DEST_DIR/$BACKUP_NAME-
then
echo "do_backup: Failed to create $LOC_DEST_DIR/$BACKUP_NAME- on local $LOC_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed to create $LOC_DEST_DIR/$BACKUP_NAME- on local $LOC_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to create $LOC_DEST_DIR/$BACKUP_NAME- on local $LOC_MOUNT_POINT" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi
fi
if [ ! -d $REM_DEST_DIR/$BACKUP_NAME- ]; then
if ! $MKDIR $REM_DEST_DIR/$BACKUP_NAME-
then
echo "do_backup: Failed to create $REM_DEST_DIR/$BACKUP_NAME- on remote $REM_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed to create $REM_DEST_DIR/$BACKUP_NAME- on remote $REM_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to create $REM_DEST_DIR/$BACKUP_NAME- on remote $REM_MOUNT_POINT" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi
fi
fi

# Loop thru each of the source directories performing the backup
######
# DAR Options used
# -v = verbose
# -w = no warn on overwriting slice files
# -s = slice file size 2147483640 =/= 2G
# -z = use gzip compression
# -m = do not compress files smaller than 1024 bytes
# -X = exclude ~ backup files
# -Z = exclude from compression
# -R = root dire of files to be backed up
# -c = base filename for the archive that is to be created. Files will be
# <base>.<number>.dar
######

for EACH_SRC_DIR in "${SRC_DIRS[@]}"; do
echo "do_backup: Starting $EACH_SRC_DIR dir backup"
echo -n "Starting $EACH_SRC_DIR dir backup at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC

# We need to modify DAR's archive name if it starts with a "." as this
# causes issues with the copy of the files to the remote destination
# directory. This snippet adds a "_" to the beginning of the filename.
BU_BASE_NAME=${EACH_SRC_DIR##*/}
if [[ ${BU_BASE_NAME::1} == "." ]]; then
BU_BASE_NAME="_$BU_BASE_NAME"
fi

if ! $DAR -v -w -s 2147483640 -z -m 1024 -X "*~" -Z "*.png" -Z "*.PNG" -Z "*.pdf" -Z "*.gif" -Z "*.GIF" -Z "*.zip" -Z "*.ZIP" -Z "*.jpg" -Z "*.jpeg" -Z "*.JPG" -Z "*.tgz" -Z "*.gz" -R "$EACH_SRC_DIR" -c $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE/"$BU_BASE_NAME-bu"
then
echo "do_backup: $EACH_SRC_DIR dir backup failed"
echo -n "!!!*** WARNING ***!!! $EACH_SRC_DIR dir backup failed at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: DAR failed backing up files to $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE/" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi

echo "do_backup: Finished $EACH_SRC_DIR dir backup"
echo -n "Finished $EACH_SRC_DIR dir backup at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC
done

# Check again to make sure the remote point is still mounted
echo "do_backup: Checking $REM_MOUNT_POINT still mounted"
echo -n "Checking $REM_MOUNT_POINT is still mounted at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
if ! $GREP $REM_MOUNT_POINT /etc/mtab
then
echo "do_backup: $REM_MOUNT_POINT not mounted, trying to mount"
if ! $MOUNT $REM_MOUNT_POINT
then
echo "do_backup: Failed to mount $REM_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed attempting to mount $REM_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to mount $REM_MOUNT_POINT before copying files." -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
fi
fi
echo "do_backup: $REM_MOUNT_POINT is still mounted AOK"
echo -n " $REM_MOUNT_POINT is still mounted AOK at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC


# Copy the backup files and lists to remote mount point
echo "do_backup: Copying backup files to $REM_MOUNT_POINT"
echo -n "Begin copy of backup files to $REM_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
if ! $CP --reply=yes -r $LOC_DEST_DIR/$BACKUP_NAME-$CURDATE/* $REM_DEST_DIR/$BACKUP_NAME-$CURDATE
then
echo "do_backup: Failed to copy backups to $REM_MOUNT_POINT"
echo -n "!!!*** WARNING ***!!! Failed to copy backups to $REM_MOUNT_POINT at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "FAILED!!! Backup for $LOC_SYSTEM_NAME" -m "Backup Failed for $LOC_SYSTEM_NAME : $CURDATE_EMAIL. Reason: Failed to copy files to $REM_MOUNT_POINT" -s $EMAIL_SERVER -a $LOGFILE_LOC
exit 1
else
echo "do_backup: Copied backups to $REM_MOUNT_POINT successfully"
echo -n "Copied backups to $REM_MOUNT_POINT successfully at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
echo " "
echo "do_backup: Backup completed successfully"
echo -n "Backup completed successfully at: " >> $LOGFILE_LOC
$DATE >> $LOGFILE_LOC
fi

echo " " >> $LOGFILE_LOC
echo "=*=*=*= Finished $BACKUP_NAME backup of $LOC_SYSTEM_NAME =*=*=*=" >> $LOGFILE_LOC
echo " " >> $LOGFILE_LOC

####################################
# Email log files
#
# The sendEmail is a perl script downloaded from:
# http://caspian.dotconf.net/menu/Software/SendEmail/
#
# It is located in the /usr/local/bin directory and uses the following switches
#
# -f From
# -t To
# -u Subject
# -m Message body
# -s Server to send SMTP.
# -a Logfile to send as an attachment
#
####################################

$SENDEMAIL -f $EMAIL_FROM -t $EMAIL_TO -u "$LOC_SYSTEM_NAME Backup Log for $CURDATE_EMAIL" -m "The Backup Log for $LOC_SYSTEM_NAME updated: $CURDATE_EMAIL" -s $EMAIL_SERVER -a $LOGFILE_LOC

exit 0

The following is an example of the configuration file needed for the above script

# Configuration file for the do_backup script
#
# (c) 2005,2006 Jim Pye - PyeNet Universal
#

#
# Email Details
#
# Email address to receive logfiles and notification of backup failures
# eg. EMAIL_TO="backup.reports@pyenet.co.nz"
EMAIL_TO="backup.reports@pyenet.co.nz"

# Email address that logfiles and notifications are sent from
# This must be a valid email address for the email server specified
# eg. EMAIL_FROM="backup.process@pyenet.co.nz"
EMAIL_FROM="backup.process@pyenet.co.nz"

# The email server used for the sending of email notifications
# eg. EMAIL_SERVER="mailer.pyenet.co.nz"
EMAIL_SERVER="mailer.pyenet.co.nz"

#
# Backup Location details
#
# The hostname of the local system
# This is the system that the backup script is running on
# eg. LOC_SYSTEM_NAME=linux-srv1
LOC_SYSTEM_NAME=linux-srv1

# The hostname of the remote system
# This is the system that the backup will be copied to
# eg. REM_SYSTEM_NAME=linux-backup-srv
REM_SYSTEM_NAME=linux-backup-srv

# Separate Sub Directories
# Backups can either be made to overwrite the previous backup or to be placed
# in their own sub directories.
# If we are going to put each backup into its own sub directory then the SUBDIR
# variable needs to be true, therefore:
#
# To _MAKE_ the subdirectories place a character (space, text) in the string
# eg. SUBDIR=" "
#
# To _NOT_ make the subdirectories make the variable an empty string
# eg. SUBDIR=""
#
SUBDIR=""

# Log File Directory
# This variable defines the directory for the log files.
# The log file will placed in this directory with the name:
# $BACKUP_NAME-backup.log
# Note the trailing / is _NOT_ needed
# eg. LOGFILE_DIR=/var/log/backups
LOGFILE_DIR=/var/log/backups

# Source Directories
# This is an array of the directories to be backed up with this configuration.
# Place each directory in quotes. This allows for directories with spaces.
# eg. SRC_DIRS=("/data/test dir with space" "/data/test-dir-wo-space")
SRC_DIRS=("/data/test dir with space" "/data/test-dir-wo-space")

# Local mount point
# This specifies the mount point for the local file system where the local
# copy of the backup is to be created. The DAR utility makes its backup
# directly to a sub directory of this mount point.
# Specifying this local mount point allows for an additional hard disk to be
# used for the local backup.
# eg. LOC_MOUNT_POINT=/data
LOC_MOUNT_POINT=/data

# Local Destination Directory
# The DAR utility creates the archive directly here first
# A subdirectory, or subdirectories, will be created below this directory using
# the $BACKUP_NAME and $CURDATE variables.
# The directory specified here must already be created and must be writable by
# the user account used to mount the filesystem.
# eg. LOC_DEST_DIR=/data/backups/linux-srv1
LOC_DEST_DIR=/data/backups/linux-srv1

# Remote mount point
# This specifies the mount point for the remote file system this is where the
# backup archives are to be copied.
# eg. REM_MOUNT_POINT=/mnt/linux-backup-srv
REM_MOUNT_POINT=/mnt/linux-backup-srv

# Remote Destination Directory
# This is where the backup archive files are copied to once they are created
# by DAR.
# The directory specified here must already be created and must be writable by
# the user account used to mount the filesystem.
# eg. REM_DEST_DIR=/mnt/linux-backup-srv/backups/linux-srv1
REM_DEST_DIR=/mnt/linux-backup-srv/backups/linux-srv1