#!/bin/bash
#
# Database Backup Script
#
# Copyright (c) 2011-12 The Metamedia Corporation, www.metamedia.us, cgray@metamedia.us
# License GPLv3   see: http://www.gnu.org/licenses/gpl.html
# Copyright (c) 2009 infyquest@gmail.com
# Copyright (c) 2002-2006 wipe_out@lycos.co.uk
# Many thanks to wipe_out and infyquest for breaking ground on this script
#
# This is extended from the AutoMySQLBackup V2.5 script from wipeout
# enhanced in autobackupmysql script from infyquest
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License v3 as published by
# the Free Software Foundation; either version 3 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 v3 for more details.
# License GPLv3    http://www.gnu.org

#=====================================================================
# Change Log
#=====================================================================
# VER 4.0b - (2015-10-09) cgray
#	Improve reporting logic
#	Changed app name and conf file name where used throughout app
# VER 4.0a - (2013-08-14) kbarnt
#	Added Support for PostgresSQL (Experimental)
#	Updated logging setup to allow for automated monitoring by tools like Nagios
# VER 3.03 - (2012-06-29) kbarnt
#	Removed Date/Time from subject line for e-mail logs.
# VER 3.02 - (2012-05-17) kbarnt
#   Fixed Platform Detection
# VER 3.01 - (2012-02-23) cgray
#   Added OPT values to conf file, along with sample options for optimal INNODB backups
#   Normalized code
#   Improved usage instructions
# VER 3.0 - (2011-04-08) cgray
#   Optional hourly backups
#   Optional backup file name prefix
#   Support for options parameters at runtime
#   Support for conf files
#   Massive refactoring to make code more cohesive and into a proper UNIX application
#   Cascading conf file loading, loading as an option from command line
#   Many minor bug fixes
# VER 1.2 - (2009-12-18) infyquest
#   Add support for configuration files
# VER 1.1 - (2009-12-10) infyquest
#   Fix for missing suffix
#   Some text changes
#   Add ignore table(s) feature
#   Make bzip2 as default compression
# VER 1.0 - (2009-12-09)
#   Initial Revamped Release based on AutoMySQLBack V2.5 Script from wipeout and patches



#=====================================================================
# Backup Rotation..
#=====================================================================
#
# Call script daily for daily backups
# Call script hourly for hourly backups


# Daily Backups are rotated weekly..
# Weekly Backups are run by default on Saturday Morning when
# cron.daily scripts are run...Can be changed with DOWEEKLY setting..
# Weekly Backups are rotated on a 5 week cycle..
# Monthly Backups are run on the 1st of the month..
# Monthly Backups are NOT rotated automatically...
# Hourly backups are rotated daily
# It may be a good idea to copy Monthly backups offline or to another
# server..
#
#=====================================================================
# Please Note!!
#=====================================================================
#
# I take no resposibility for any data loss or corruption when using
# this script..
# This script will not help in the event of a hard drive crash. If a 
# copy of the backup has not be stored offline or on another PC..
# You should copy your backups offline regularly for best protection.
#
# Happy backing up...
#
#=====================================================================
# Restoring
#=====================================================================
# First you will need to uncompress the backup file.
# eg.
# gunzip file.gz (or bunzip2 file.bz2)
#
# Next you will need to use the mysql client to restore the DB from the
# sql file.
# ie.
#     mysql --user=username --pass=password --host=dbserver databasename < /path/file.sql
# or
#     mysql --user=username --pass=password --host=dbserver -e "source /path/file.sql" databasename
#
# NOTE: Make sure you use "<" and not ">" in the above command because
# you are piping the file.sql to mysql and not the other way around.


PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/mysql/bin
PROJECT_NAME=$(basename "$0")
PROJECT_VERSION=4.0b

#
# Detect the platform
#
PLATFORM='darwin'
UNAMESTR=`uname`
if [[ "$UNAMESTR" == 'Darwin' ]]; then
	PLATFORM='darwin'
elif [[ "$UNAMESTR" == 'Linux' ]]; then
	PLATFORM='linux'
fi

#
# Show splash screen
#
showSplashScreen () {
	if [ "$TERM" != "dumb" ]; then
		# Terminal Check
		case $TERM in
		# for the most important terminal types we directly know the sequences
		xterm|xterm*|vt220|vt220*)
			 bold=`awk 'BEGIN { printf("%c%c%c%c", 27, 91, 49, 109); }' </dev/null 2>/dev/null`
			norm=`awk 'BEGIN { printf("%c%c%c", 27, 91, 109); }' </dev/null 2>/dev/null`
			;;
		vt100|vt100*|cygwin)
			bold=`awk 'BEGIN { printf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); }' </dev/null 2>/dev/null`
			norm=`awk 'BEGIN { printf("%c%c%c%c%c", 27, 91, 109, 0, 0); }' </dev/null 2>/dev/null`
			;;
		esac
		
		if [ -t 0 ]; then
			color_1=""
			color_2=""
		else
			color_1=`echo -en "\e[37;40m"`
			color_2=`echo -en "\e[37;41m"`
		fi
	
	
		clear
		cat <<X
${color_1} +--------------------------------------------------------------------+ 
 |                                                                    | 
 |                           ${color_2} ${PROJECT_NAME} ${color_1}                            | 
 |                                                                    | 
 |                           Version ${PROJECT_VERSION}                              | 
 |                                                                    | 
 |                      Copyright (c) 2002 - 2015                     | 
 |                  License GPLv3    http://www.gnu.org               | 
 |                                                                    | 
 |                  The Metamedia Corporation / HappyMac              | 
 |                           cgray@metamedia.us                       | 
 |                    http://www.happymac.info/                       | 
 |                                                                    | 
 |         Based on automysqlbackup script v2.5                       | 
 |            by wipe_out@lycos.co.uk                                 | 
 |              http://sourceforge.net/projects/automysqlbackup/      | 
 |                                                                    | 
 |         enhanced in the autobackupmysql script v1.2                | 
 |            by infyquest@gmail.com                                  | 
 |              http://sourceforge.net/projects/autobackupmysql/      | 
 |                                                                    | 
 +--------------------------------------------------------------------+ 
Platform detected: ${PLATFORM}
X
		tput sgr0
	fi
}

#
# Set defaults variable
#
setDefaultsVariable () {
	export DEFAULTS=`cat <<END
#=====================================================================
#=====================================================================
# 
# Sample Configuration File for backupdb
#
#
#=====================================================================
#
# Set the variables below to those for your system and needs
#
# To use:
# 1. Rename this file and locate at: /etc/backupdb.conf , or
# 2. When invoking backupdb use the -c flag and the full path to the conf file,
#        ie. sh backupdb -c /Users/cgray/Documents/current-work/backupdb.conf
#        This allows you to use different settings when running backupdb at different times for different purposes


# Username and password to access the MySQL server
# must have at least SELECT permission to ALL databases being backed-up
USERNAME='dbuser'
PASSWORD='password'

# Host name (or IP address) of MySQL server to backup
# to backup multiple servers make copies of this file and set the options for that server
DBHOST='localhost'

# List of DBNAMES to backup
# e.g. "DB1 DB2 DB3" or "all"
# if a DB name has a space in the name replace the space with a % e.g. "data base" will become "data%base"
# NOTE: Spaces in DB names may not work correctly when SEPDIR=no.
DBNAMES="all"

# Backup directory location
# enter the full path and directory name (if directory does not exist, it will be created)
BACKUPDIR="/mysql-backup"

# Mail setup
# What would you like to be mailed to you?
# - log   : send only log file
#            (requires mail)
# - files : send log file and sql files as attachments
#            (requires mutt)
# - stdout : will simply output the log to the screen if run manually.
# - quiet : Only send logs if an error occurs to the MAILADDR.
MAILCONTENT="stdout"

# Set the maximum allowed email size in K. (4000 = approx 5MB email [see docs])
# This is the size before it is encoded to be sent as an email
# so if your mail server will allow a maximum mail size of 5MB I would suggest setting 25% smaller, ie 4000
MAXATTSIZE="4000"

# Email Address to send notifications to?
# to send to multiple email addresses use a space seperated list.
MAILADDR="user@example.com"

# ============================================================
# === ADVANCED OPTIONS ===
#=============================================================

# List of DBBNAMES for Monthly Backups.
# always include "mysql" in this list to backup your user/password information along with any other DBs that you only feel need to be backed up monthly.
# (if using a hosted server then you should probably remove "mysql" as your provider will be backing this up)
# NOTE: If DBNAMES="all" then MDBNAMES has no effect as all DBs will be backed up anyway.
MDBNAMES="mysql \$DBNAMES"

# List of DBNAMES to EXCLUDE if DBNAMES are set to "all"
# otherwise this option will not be used.
# Udseful if you want to backup all dbs, but you want exclude some of them. (eg. a db is to big).
DBEXCLUDE=""

# List of tables to exclude from the backup (in form db.table)
TABLEEXCLUDE=""

# Include CREATE DATABASE in backup?
# On restore, uses the create database command with the same name as the original database
# If set to "no" you can specify the database name to use ar restore
# NOTE: Not used if SEPDIR=no
CREATE_DATABASE=yes

# Separate backup directory and file for each DB? (yes or no)
# A single file allows restoring an entire server using one command, but can result in massive files
SEPDIR=yes

# Which day do you want weekly backups? (1 to 7 where 1 is Monday)
DOWEEKLY=6

# Do hourly intraday backups?
# If hourly backups are desired, this script should be invoked every hour
# DODAILY allowes you to set which hour of the day to perform  daily, weekly, and monthly backups
# and only applies if hourly is enabled (00 to 23, where 00 is midnight)
HOURLY=no
DODAILY=02

# Add prefix to backup file name?
# Files with matching prefixes are rotated separately from non-matching
FILE_PREFIX=""

# Choose Compression type. (gzip or bzip2)
# bzip2 will produce slightly smaller files but is more processor intensive so may take longer to complete.
COMP=bzip2

# Enable inline or piped compression.
# (may  reduce the time taken for completion)
PIPECOMP=yes

# Compress communications between backup server and MySQL server?
# useful to save bandwidth when backing up a remote MySQL server over the network.
COMMCOMP=no

# Additionally keep a copy of the most recent backup in a seperate directory.
# Useful so that it can be downloaded bt third party scripts.
LATEST=no

#  The maximum size of the buffer for client/server communication. e.g. 16MB (maximum is 1GB)
# If the DB's being backed up make use of large BLOB fields then you may need
# to increase the MAX_ALLOWED_PACKET setting, for example 16MB..
MAX_ALLOWED_PACKET=

#  For connections to localhost. Sometimes the Unix socket file must be specified.
# When connecting to localhost as the DB server (DBHOST=localhost) sometimes
# the system can have issues locating the socket file.. This can now be set
# using the SOCKET parameter.. An example may be SOCKET=/private/tmp/mysql.sock
SOCKET=

# Use PREBACKUP and POSTBACKUP to specify Per and Post backup commands
# or scripts to perform tasks either before or after the backup process.

# Command to run before backups (uncomment to use)
#PREBACKUP="/etc/mysql-backup-pre"

# Command run after backups (uncomment to use)
#POSTBACKUP="/etc/mysql-backup-post"

# Additional mysqldump options
# See mysqldump documentation for additional options, ie. http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
#    Quote identifiers and default mysqldump options
OPT="--quote-names --opt"
#
# OR if you are using INNODB tables, consider using the following:
#    large datasets may causing availability issues due to tabel locking during backup, so this will work better
#    this wraps and then restores compatible defaults normally available
#OPT="--quote-names --single-transaction --skip-opt --add-drop-table --add-locks --create-options --disable-keys --extended-insert --quick --set-charset"

END`;
}


#
# Load conf file
#
loadConfFile() {
	if [ $CONFFILE ] ; then
		if [ -f $CONFFILE ] ; then
			echo "Using conf file: $CONFFILE"
			source $CONFFILE
		else
			echo "ERROR: Could not load config file at: $CONFFILE"
			echo "Use -h for help and usage instructions (including how to make a sample conf file)"
			exit 1
		fi
	else
		echo "No conf file specified: use -h for help and usage instructions"
		exit 1
	fi
}


#
# Make sample conf file
#
makeSampleConfFile() {
	# file already exists? (this will error)
	if [ -f $OPTARG ] ; then
		SAMPLECONFFILEPATH=$OPTARG
	# valid directory?
	elif [[ -d "${OPTARG}" && ! -L "${OPTARG}" ]] ; then
		SAMPLECONFFILEPATH=$OPTARG/backupdb.conf
	else
		SAMPLECONFFILEPATH=$OPTARG
	fi
	
	if [ -f $SAMPLECONFFILEPATH ] ; then
		echo "ERROR: A file by this name already exists at: $SAMPLECONFFILEPATH"
		exit 1
	fi

	echo "$DEFAULTS" >> $SAMPLECONFFILEPATH
	echo "Sample conf file created at: $SAMPLECONFFILEPATH"
	echo "Edit this file for your environment and backup needs."
	echo "See the instructions in this file for usage."
}


# Print help
#
printHelp() {
cat << TXT

${bold}$(basename "$0")${norm} Script for MySQL database backup

 Usage: $(basename "$0") <action> <path> 
 [ -c ] <path>           : path to conf file
 [ -m ] <path>           : create new sample conf file at path
                         :
 [ -u ] <db-username>    : mysql db user name
 [ -p ] <password>       : password for mysql db user
                         :
 [ -h ]                  : display this help message.

TXT
	exit 0
}

# Add this above if/when we add a real man page for this script
#                         : SEE "man $(basename "$0")" for instructions.

# Create required directories
createRequiredDirectories() {
	if [ ! -e "$BACKUPDIR" ]		# Check Backup Directory exists.
		then
		mkdir -p "$BACKUPDIR"
	fi

	if [ ! -e "$BACKUPDIR/daily" ]		# Check Daily Directory exists.
		then
		mkdir -p "$BACKUPDIR/daily"
	fi

	if [ ! -e "$BACKUPDIR/weekly" ]		# Check Weekly Directory exists.
		then
		mkdir -p "$BACKUPDIR/weekly"
	fi

	if [ ! -e "$BACKUPDIR/monthly" ]	# Check Monthly Directory exists.
		then
		mkdir -p "$BACKUPDIR/monthly"
	fi

	if [ ! -e "$BACKUPDIR/logs" ]	# Check Logs Directory exists.
		then
		mkdir -p "$BACKUPDIR/logs"
	fi

	if [ "$LATEST" = "yes" ]
		then
			if [ ! -e "$BACKUPDIR/latest" ]	# Check Latest Directory exists.
			then
				mkdir -p "$BACKUPDIR/latest"
			fi
		eval rm -f "$BACKUPDIR/latest/*"
	fi

	if [ "$HOURLY" = "yes" ]
	then
		if [ ! -e "$BACKUPDIR/hourly" ]	# Check Hourly Directory exists.
		then
			mkdir -p "$BACKUPDIR/hourly"
		fi
	fi
}

# ----------------------------------------------------
# Beginning of application
showSplashScreen


# Set the defaults variable, then load it
setDefaultsVariable
eval "$DEFAULTS"


#
# Ensure that at least one option value was provided
#
#if [ $# -lt 1 ]
#	then
#	printHelp
#	exit 1
#fi


#
# Set passed option values (overriding default conf)
#
setopts () {
	while getopts "hc:m:u:p:" optname
		do
			case "$optname" in
				"h") 
					printHelp
					exit 0;;
				"m") 
					makeSampleConfFile
					exit 0;;
				"c")
					CONFFILE=$OPTARG
					loadConfFile;;
				"u") 
					USERNAME=$OPTARG;;
				"p") 
					PASSWORD=$OPTARG;;
				*)	# Should not occur
					echo "ERROR: Unknown option or argument : use -h for help and usage instructions"
					exit 0;;
			esac
		done
	# return $OPTIND
}
setopts "$@"

# If CONFFILE was not set, try to find the default and load it
if [ ! $CONFFILE ];
	then
		CONFFILE=/etc/backupdb.conf
		loadConfFile
fi

#
# Test that we have sufficient parameters to execute
#
if [ "$USERNAME" = "dbuser" ];
	then
		echo "ERROR: Database USERNAME must be set, either in conf file or as command line option"
		echo "Use -h for help and usage instructions"
		exit 1
fi
if [ "$PASSWORD" = "password" ];
	then
		echo "ERROR: Database PASSWORD must be set, either in conf file or as command line option"
		echo "Use -h for help and usage instructions"
		exit 1
fi

createRequiredDirectories

#
# Set env-specific backup variable(s)
#
	# Using the offset is not supported by date on RHEL
	#
	# Set OFFSET>0 to test rotation, units: [ymwdHMS], cannot mix units
	#OFFSET="-566H"

	if [ $PLATFORM = "darwin" ];
		# Account for darwin-specific date syntax (UNIX)
		then
		if [ $OFFSET ];
			then
			STARTTS=`date -v$OFFSET +%s`
		else
			STARTTS=`date +%s`
		fi
		
		DATE=`date -r $STARTTS +%Y-%m-%d_%H%M`				# Datestamp e.g 2002-09-21_13:35
		HNOD=`date -r $STARTTS +%H`							# Hour number of the day e.g. 09 (in 24 hour notation)
		DOW=`date -r $STARTTS +%A`							# Day of the week e.g. Monday
		DNOW=`date -r $STARTTS +%u`							# Day number of the week 1 to 7 where 1 represents Monday
		DOM=`date -r $STARTTS +%d`							# Date of the Month e.g. 27
		M=`date -r $STARTTS +%B`							# Month e.g January
		W=`date -r $STARTTS +%V`							# Week Number e.g 37
		LOGFILE=$BACKUPDIR/logs/$DBHOST-`date -r $STARTTS +%F_%T`.log			# Logfile Name
		LOGERR=$BACKUPDIR/logs/ERRORS_$DBHOST-`date -r $STARTTS +%F_%T`.log		# Logfile Name
	else
		# Use linux-specific date syntax
		if [ $OFFSET ];
			then
			####STARTTS=`date -v $OFFSET +%s`
			# TO DO: IMPLEMENT PROPER OFFSET SETTING OF THIS VARIABLE FOR LINUX
			STARTTS=`date '+%F %T'`
		else
			STARTTS=`date '+%F %T'`
		fi
		DATE=`date -d "$STARTTS" +%Y-%m-%d_%H%M`				# Datestamp e.g 2002-09-21_13:35
		HNOD=`date -d "$STARTTS" +%H`							# Hour number of the day e.g. 09 (in 24 hour notation)
		DOW=`date -d "$STARTTS" +%A`							# Day of the week e.g. Monday
		DNOW=`date -d "$STARTTS" +%u`							# Day number of the week 1 to 7 where 1 represents Monday
		DOM=`date -d "$STARTTS" +%d`							# Date of the Month e.g. 27
		M=`date -d "$STARTTS" +%B`								# Month e.g January
		W=`date -d "$STARTTS" +%V`								# Week Number e.g 37
		LOGFILE=$BACKUPDIR/logs/$DBHOST-`date -d "$STARTTS" +%F_%T`.log			# Logfile Name
		LOGERR=$BACKUPDIR/logs/ERRORS_$DBHOST-`date -d "$STARTTS" +%F_%T`.log		# Logfile Name
	fi

	BACKUPFILES=""


# IO redirection for logging.
echo "Progress and error logs are written to: $BACKUPDIR/logs, and will be displayed here after completion"
touch $LOGFILE
exec 6>&1           # Link file descriptor #6 with stdout.
                    # Saves stdout.
exec > $LOGFILE     # stdout replaced with file $LOGFILE.
touch $LOGERR
exec 7>&2           # Link file descriptor #7 with stderr.
                    # Saves stderr.
exec 2> $LOGERR     # stderr replaced with file $LOGERR.

echo "Backups are written to: $BACKUPDIR"
echo ======================================================================
echo Backup of Database Server: $DBHOST
echo "Database(s)              : $DBNAMES"
echo ======================================================================
if [ $OFFSET ];
	then
		echo "WARNING: EXECUTION TIME OFFSET FOR TESTING : $OFFSET"
fi
echo Backup Start Time $DATE
echo "Day of Month: $DOM        Day of Week: $DOW        Hour: $HNOD"
echo ======================================================================

# Add --compress mysqldump option to $OPT
if [ "$COMMCOMP" = "yes" ];
	then
		OPT="$OPT --compress"
	fi

# Add --compress mysqldump option to $OPT
if [ "$MAX_ALLOWED_PACKET" ];
	then
		OPT="$OPT --max_allowed_packet=$MAX_ALLOWED_PACKET"
	fi

# Set the suffix for compressed file
if [ "$COMP" = "gzip" ];
	then
		SUFFIX=".gz"
elif [ "$COMP" = "bzip2" ];
	then
		SUFFIX=".bz2"
else
		SUFFIX=""
fi


# Functions

# Database dump function
dbdump () {
if [ "$PIPECOMP" = "yes" ]; then
	mysqldump --user=$USERNAME --password=$PASSWORD --host=$DBHOST $OPT $1 | $COMP > "$2$SUFFIX"
else
	mysqldump --user=$USERNAME --password=$PASSWORD --host=$DBHOST $OPT $1 > $2
fi
return 0
}

# Compression function plus latest copy
compression () {
if [ "$COMP" = "gzip" ]; then
	if [ "$PIPECOMP" = "no" ]; then
		gzip -f "$1"
		echo
		echo Backup Information for "$1"
		gzip -l "$1.gz"
	fi
elif [ "$COMP" = "bzip2" ]; then
	if [ "$PIPECOMP" = "no" ]; then
		echo Compression information for "$1.bz2"
		bzip2 -f -v $1 2>&1
	fi
else
	echo "No compression option set, check advanced settings"
fi
if [ "$LATEST" = "yes" ]; then
	cp "$1$SUFFIX" "$BACKUPDIR/latest/"
fi	
return 0
}

#
#
#	EXECUTION BEGINS HERE
#
#


# Run command before we begin
if [ "$PREBACKUP" ]
	then
	echo ======================================================================
	echo "Prebackup command output."
	echo
	eval $PREBACKUP
	echo
	echo ======================================================================
	echo
fi

# Add --ignore-table options to $OPT
if [ -n "$TABLEEXCLUDE" ]; then
	for table in $TABLEEXCLUDE ; do
		OPT="${OPT} --ignore-table=${table}"
	done
fi

if [ "$SEPDIR" = "yes" ]; then # Check if CREATE DATABASE should be included in Dump
	if [ "$CREATE_DATABASE" = "no" ]; then
		OPT="$OPT --no-create-db"
	else
		OPT="$OPT --databases"
	fi
else
	OPT="$OPT --databases"
fi

# Hostname for LOG information
if [ "$DBHOST" = "localhost" ]; then
	HOST=`hostname`
	if [ "$SOCKET" ]; then
		OPT="$OPT --socket=$SOCKET"
	fi
else
	HOST=$DBHOST
fi

# Always exclude information_schema and performance_schema
if [ "$DBEXCLUDE" = "" ]; then
	DBEXCLUDE="information_schema performance_schema"
else
	DBEXCLUDE="$DBEXCLUDE information_schema performance_schema"
fi

# If backing up all DBs on the server
if [ "$DBNAMES" = "all" ]; then
	DBNAMES="`mysql --user=$USERNAME --password=$PASSWORD --host=$DBHOST --batch --skip-column-names -e "show databases"| sed 's/ /%/g'`"

	# If DBs are excluded
	for exclude in $DBEXCLUDE
	do
	#	DBNAMES=`echo $DBNAMES | sed "s/\b$exclude\b//g"`
		DBNAMES=${DBNAMES/$exclude}
	done
	echo $DBNAMES
fi

# Monthly Backup of databases
echo "Monthly Backup(s)"
if [ $DOM = "01" ] && [ $HOURLY = "no" -o $HNOD = $DODAILY ]; then
	if [ "$SEPDIR" = "yes" ]; then
		for DB in $DBNAMES
		do
			DB="`echo $DB | sed 's/%/ /g'`"	# Prepare $DB for using
			echo "+ Monthly Backup of Database ( $DB )"
			
			if [ ! -e "$BACKUPDIR/monthly/$DB" ]		# Check monthly DB Directory exists.
			then
				mkdir -p "$BACKUPDIR/monthly/$DB"
			fi
			
			FILEPATHBASENAME="$BACKUPDIR/monthly/$DB/$FILE_PREFIX$DB.month_$M"
			#ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
			#if [ "$?" = "0" ]; then
			#	echo "    Deleting outdated monthly backup file(s):"
			#	eval rm -fv "$FILEPATHBASENAME.*"
			#else
			#	echo "    There are no outdated monthly backup files to be deleted"
			#fi
			echo "    We do not delete monthly backup files"

			dbdump "$DB" "$FILEPATHBASENAME.$DATE.sql"
			compression "$FILEPATHBASENAME.$DATE.sql"
			BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
			echo "    (backup completed)"
		done
	else
		FILEPATHBASENAME="$BACKUPDIR/monthly/$FILE_PREFIX""multiple-databases.month_$M"
		#ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
		#if [ "$?" = "0" ]; then
		#	echo "    Deleting outdated monthly backup file(s):"
		#	eval rm -fv "$FILEPATHBASENAME.*"
		#else
		#	echo "    There are no outdated monthly backup files to be deleted"
		#fi
		echo "    We do not delete monthly backup files"
		
		dbdump "$DBNAMES" "$FILEPATHBASENAME.$DATE.sql"
		compression "$FILEPATHBASENAME.$DATE.sql"
		BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
		echo "    (backup completed)"
	fi
else
	echo " - Monthy backups occur on the first of each month on the $DODAILY hour."
fi
echo ----------------------------------------------------------------------


# Weekly Backup of databases
echo "Weekly Backup(s)"
if [ $DNOW = $DOWEEKLY ] && [ $HOURLY = "no" -o $HNOD = $DODAILY ]; then
		if [ "$W" -le 05 ];then # determine files which should be rotated
			REMW=`expr 48 + $W`
		elif [ "$W" -lt 15 ];then
			REMW=0`expr $W - 5`
		else
			REMW=`expr $W - 5`
		fi
	if [ "$SEPDIR" = "yes" ]; then
		for DB in $DBNAMES
		do
			DB="`echo $DB | sed 's/%/ /g'`"	# Prepare $DB for using
			echo "+ Weekly Backup of Database ( $DB )"
			
			if [ ! -e "$BACKUPDIR/weekly/$DB" ]		# Check Weekly DB Directory exists.
			then
				mkdir -p "$BACKUPDIR/weekly/$DB"
			fi
			
			FILEPATHBASENAME="$BACKUPDIR/weekly/$DB/$FILE_PREFIX$DB.week_$REMW"
			ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
			if [ "$?" = "0" ]; then
				echo "    Deleting outdated weekly backup file(s):"
				eval rm -fv "$FILEPATHBASENAME.*"
			else
				echo "    There are no outdated weekly backup files to be deleted"
			fi

			dbdump "$DB" "$FILEPATHBASENAME.$DATE.sql"
			compression "$FILEPATHBASENAME.$DATE.sql"
			BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
			echo "    (backup completed)"
		done
	else
		FILEPATHBASENAME="$BACKUPDIR/weekly/$FILE_PREFIX""multiple-databases.week_$REMW"
		ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
		if [ "$?" = "0" ]; then
			echo "    Deleting outdated weekly backup file(s):"
			eval rm -fv "$FILEPATHBASENAME.*"
		else
			echo "    There are no outdated weekly backup files to be deleted"
		fi
		dbdump "$DBNAMES" "$FILEPATHBASENAME.$DATE.sql"
		compression "$FILEPATHBASENAME.$DATE.sql"
		BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
		echo "    (backup completed)"
	fi
else
	echo " - Weekly backups occur on the $DODAILY hour of $DOWEEKLY day of each week on the $DODAILY hour.."
fi
echo ----------------------------------------------------------------------



# Daily Backup of databases
echo "Daily Backup(s)"
if [ "$HOURLY" = "no" ] || [ $HNOD = $DODAILY ]; then
	if [ "$SEPDIR" = "yes" ]; then
		for DB in $DBNAMES
		do
			DB="`echo $DB | sed 's/%/ /g'`"	# Prepare $DB for using
			echo "+ Daily Backup of Database ( $DB )"
			
			if [ ! -e "$BACKUPDIR/daily/$DB" ]		# Check Daily DB Directory exists.
			then
				mkdir -p "$BACKUPDIR/daily/$DB"
			fi
			
			FILEPATHBASENAME="$BACKUPDIR/daily/$DB/$FILE_PREFIX$DB.day_$DOW"
			ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
			if [ "$?" = "0" ]; then
				echo "    Deleting outdated daily backup file(s):"
				eval rm -fv "$FILEPATHBASENAME.*"
			else
				echo "    There are no outdated daily backup files to be deleted"
			fi

			dbdump "$DB" "$FILEPATHBASENAME.$DATE.sql"
			compression "$FILEPATHBASENAME.$DATE.sql"
			BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
			echo "    (backup completed)"
		done
	else
		FILEPATHBASENAME="$BACKUPDIR/daily/$FILE_PREFIX""multiple-databases.day_$DOW"
		ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
		if [ "$?" = "0" ]; then
			echo "    Deleting outdated daily backup file(s):"
			eval rm -fv "$FILEPATHBASENAME.*"
		else
			echo "    There are no outdated daily backup files to be deleted"
		fi
		dbdump "$DBNAMES" "$FILEPATHBASENAME.$DATE.sql"
		compression "$FILEPATHBASENAME.$DATE.sql"
		BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
		echo "    (backup completed)"
	fi
else
	echo " - Daily backups occur on the $DODAILY hour of each day."
fi
echo ----------------------------------------------------------------------


# Hourly Backup of databases
echo "Hourly Backup(s)"
if [ "$HOURLY" = "yes" ] && [ $HNOD != $DODAILY ]; then
	if [ "$SEPDIR" = "yes" ]; then
		for DB in $DBNAMES
		do
			DB="`echo $DB | sed 's/%/ /g'`"	# Prepare $DB for using
			echo "+ Hourly Backup of Database ( $DB )"
			
			if [ ! -e "$BACKUPDIR/hourly/$DB" ]		# Check Daily DB Directory exists.
			then
				mkdir -p "$BACKUPDIR/hourly/$DB"
			fi
			
			FILEPATHBASENAME="$BACKUPDIR/hourly/$DB/$FILE_PREFIX$DB"".hour_$HNOD"
			ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
			if [ "$?" = "0" ]; then
				echo "    Deleting outdated hourly backup file(s):"
				eval rm -fv "$FILEPATHBASENAME.*"
			else
				echo "    There are no outdated hourly backup files to be deleted"
			fi

			dbdump "$DB" "$FILEPATHBASENAME.$DATE.sql"
			compression "$FILEPATHBASENAME.$DATE.sql"
			BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
			echo "    (backup completed)"
		done
	else
		FILEPATHBASENAME="$BACKUPDIR/hourly/$FILE_PREFIX""multiple-databases.hour_$HNOD"
		ls -1 $FILEPATHBASENAME.* > /dev/null 2>&1
		if [ "$?" = "0" ]; then
			echo "    Deleting outdated hourly backup file(s):"
			eval rm -fv "$FILEPATHBASENAME.*"
		else
			echo "    There are no outdated hourly backup files to be deleted"
		fi
		dbdump "$DBNAMES" "$FILEPATHBASENAME.$DATE.sql"
		compression "$FILEPATHBASENAME.$DATE.sql"
		BACKUPFILES="$BACKUPFILES $FILEPATHBASENAME.$DATE.sql$SUFFIX"
		echo "    (backup completed)"
	fi
elif [ "$HOURLY" = "yes" ]; then
	echo " - Hourly backups are not performed concurrent with daily backups."
else
	echo " - Hourly backups are not enabled. See notes in conf file if you desire this capability."
fi
echo ----------------------------------------------------------------------


echo Backup End Time `date`
echo ======================================================================
echo Total disk space used for backup storage..
echo Size - Location
echo `du -hs "$BACKUPDIR"`
echo
echo ======================================================================

# Run command when we're done
if [ "$POSTBACKUP" ]; then
	echo ======================================================================
	echo "Postbackup command output."
	echo
	eval $POSTBACKUP
	echo
	echo ======================================================================
fi

#
# Report and cleanup
#
report () {
	ERRORS=0;

	# Clean up IO redirection
	exec 1>&6 6>&-      # Restore stdout and close file descriptor #6.
	exec 1>&7 7>&-      # Restore stdout and close file descriptor #7.
	
	#Remove Password warnings (MySQL 5.6+) from error log
	grep -v -e "Warning: Using a password on the command line interface can be insecure." $LOGERR > $LOGERR.tmp
	mv $LOGERR.tmp $LOGERR

	# any errors written to error log?
	# stderr file is (sometimes) not updated until after script terminates !!!!
	if [ -s "$LOGERR" ]; then
		echo "  - Error(s) appear in error log file";
		((ERRORS++));
	fi


	if [ $ERRORS -gt 0 ]; then
		REPORT_SUBJECT="ERRORS Backupdb Log for $HOST - $DATE";
		LOGFILES="$LOGFILE $LOGERR";
		STATUS=1
	else
		REPORT_SUBJECT="SUCCESSFUL Backupdb Log for $HOST";
		LOGFILES="$LOGFILE";
		STATUS=0
	fi

	# determine report disposition
	DELIVERED=1;
	# email files
	if [ "$MAILCONTENT" = "files" ]; then

		#Get backup file size
		ATTSIZE=`du -c $BACKUPFILES | grep "[[:digit:][:space:]]total$" |sed s/\s*total//`
		if [ $MAXATTSIZE -ge $ATTSIZE ]; then
			BACKUPFILES=`echo "$BACKUPFILES" | sed -e "s# # -a #g"`	#enable multiple attachments
			mutt -s "$REPORT_SUBJECT" $BACKUPFILES $MAILADDR < $LOGFILES		#send via mutt
			if [ $? -eq 0 ]; then
				DELIVERED=0;
			fi
		else
			cat $LOGFILES | mail -s "WARNING! - Backupdb exceeds set maximum attachment size on $HOST - $DATE" $MAILADDR
			if [ $? -eq 0 ]; then
				DELIVERED=0;
			fi
		fi
		
	# were we able to write the logfile? If not, then we need to report that
	elif ! [ -w "$LOGFILE" ]; then
		echo "Write permission is NOT granted on $LOGFILE. See stdout." | mail -s "ERRORS Backupdb Log for $HOST - $DATE" $MAILADDR
		if [ $? -eq 0 ]
		then
			DELIVERED=0;
		fi
		
	# email log
	elif [ "$MAILCONTENT" = "log" ]; then
		cat $LOGFILE | mail -s "$REPORT_SUBJECT" $MAILADDR
		if [ $? -eq 0 ]
		then
			DELIVERED=0;
		fi

	# only email log on error
	elif [ "$MAILCONTENT" = "quiet" ]; then
	
		if [ $ERRORS -gt 0 ]; then
			cat $LOGFILE | mail -s "$REPORT_SUBJECT" $MAILADDR
			if [ $? -eq 0 ]; then
				DELIVERED=0;
			fi
		fi
	fi


	# always send report to stdout
	if [ $ERRORS -gt 0 ]; then
		cat "$LOGFILE";
		echo;
		cat "$LOGERR";
		echo "###### WARNING ######";
		echo "Errors reported during execution: $ERRORS";
	else
		cat "$LOGFILE";
	fi

	# Clean up Logfiles
	if [ $DELIVERED -gt 0 ]; then
		echo "  . Report NOT delivered, so log files preserved: error: $?";
	else
		eval rm -f "$LOGFILE";
		eval rm -f "$LOGERR";
		echo "  . Report delivered, so log files deleted";
	fi

	exit $STATUS;
}

report;

