#! /bin/sh
#
# 'save_db.sh', a script to save all MySQL databases in /var/lib/mysql
#
# This must be run as root, best done via cron. The corresponding line
# in /etc/crontab for a backup every night at 02:10 is:
#
#     10 2 * * *    root   /root/bin/save_db.sh
#
# -----------------------------------------------------------------
# History: 
# 2000-08-14, JHa (first version, in tcsh).
# 2000-10-05, JHa (now restarts mysql).
# 2001-11-08, JHa (mysql now in /var/lib/mysql)
# 2002-08-08, JHa (completely rewritten for bash. Check for mounted 
# 	      drive; try to mount and exit if not mountable.)
# 2002-10-01, JHa (added /var/log/mysql directory)
# 2003-01-11, JHa (added many error checks;
#                  now .tar.gz instead of .tgz)
# 2005-01-10, JHa (HOSTNAME from environment; License now GPL *v2*)
# 2005-03-18, JHa (fix in checkfor() error message)
# -----------------------------------------------------------------
# Copyright (c) 2000-2005 Joerg Hau <joerg.hau(at)dplanet.ch>.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License as published by the Free Software Foundation.
#
# 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.
# -----------------------------------------------------------------

#
# --- Adjust these lines to your local setup ---
#

# $SAVEDEST is a mount point that must appear in /etc/fstab !
#
SAVEDEST="/mnt/inst/alpha"
SAVEDIR="$SAVEDEST/database"

# directory and files to be archived
# do not forget the log files ...
#
DB_BASE_DIR="/var"
DB_FILES="lib/mysql log/mysql"

# start/stop using only the mysql wrapper
#
MYSQL="/etc/rc.d/init.d/mysqld"

# Be verbose or not (empty string = no)
#
VERBOSE=""

# Get the system name
# (without the domain name)
#
NAME=${HOSTNAME%%.*}

#
# --- (usually) no user adjustable parts below this line :-)
#

if [ $VERBOSE ] ; then echo `date --iso-8601=sec`", $0 started." ; fi


# -----------------------------------------------------------------
# subroutine to check for some required executables
# argument: (list of) programs to test for
# will exit with rc=1 if any program was not found
# -----------------------------------------------------------------
function checkfor()
{
for i in $*; do
    PROG=`which $i`
    if [ $? != 0 ]; then
	echo "*** '$i' command not found, exiting. ***"
	exit 1
    fi
done
}

checkfor tar date grep gzip cat echo mount umount $MYSQL


# -----------------------------------------------------------------
# subroutine to check error status of last command
# argument: error message to be displayed
# will exit with rc=2 if errorlevel was not 0
# -----------------------------------------------------------------
function errcheck()
{
if [ $? != 0 ]; then
    echo $1
    # need to restart DB before exiting so the system is operational!
    $MYSQL restart > /dev/null
    exit 2
fi
}


#
# --- Here we go ! --- #
#


# See if $SAVEDEST is mounted: if yes, it is listed in /etc/mtab.
# if it is not mounted, try to mount. If unsuccessful, exit.
#
WAS_MOUNTED=`grep -c $SAVEDEST /etc/mtab`
if [ $WAS_MOUNTED = "0" ] ; then
    if [ $VERBOSE ] ; then echo -n "$SAVEDEST is not mounted. Trying to mount ... " ; fi
    mount $SAVEDEST
    errcheck "*** ERROR: Cannot mount $SAVEDEST. Exiting."
    if [ $VERBOSE ] ; then echo "$SAVEDEST mounted successfully." ; fi
else
    if [ $VERBOSE ] ; then echo "$SAVEDEST is already mounted." ; fi
fi

# check if target dir is accessible at all
#
if [ ! -w $SAVEDIR ] ; then
    echo "*** Error: '$SAVEDIR' is not writeable! ***"
    $MYSQL restart > /dev/null
    exit 2
fi

# Stop mysql daemon. This is not really necessary (hot backup works),
# but I prefer it that way ;-)
#
$MYSQL stop > /dev/null

# derive archive name from system name and actual date/time
#
ARCH=${NAME}.mysql.`date +%Y%m%dT%H%M`.tar

# Create a tar archive (-c) and verify (-W)
#
if [ $VERBOSE ] ; then echo -n "Archiving MySQL database and logs of $NAME to $SAVEDIR/$ARCH ..." ; fi
tar -cWf $SAVEDIR/$ARCH -C $DB_BASE_DIR $DB_FILES
errcheck "*** Archival of $ARCH failed, exiting."
if [ $VERBOSE ] ; then echo " done."; fi

if [ $VERBOSE ] ; then echo -n "Compressing archive $SAVEDIR/$ARCH ..."; fi
gzip -9 $SAVEDIR/$ARCH
errcheck "*** Compression of $ARCH failed, exiting."
if [ $VERBOSE ] ; then echo " done."; fi

# Restart mysql stuff
#
$MYSQL start > /dev/null

# If $SAVEDEST was initially unmounted, unmount it again:
#
if [ $WAS_MOUNTED = "0" ] ; then
    if [ $VERBOSE ] ; then echo -n "$SAVEDEST was not mounted before. Unmounting ... " ; fi
    sync
    umount $SAVEDEST
    errcheck "*** WARNING: Cannot unmount $SAVEDEST. ***"
    if [ $VERBOSE ] ; then echo "$SAVEDEST unmounted successfully." ; fi
fi

if [ $VERBOSE ] ; then echo `date --iso-8601=sec`", Backup script ended." ; fi

# set an exit status.
test "$return" = "0" || exit 1
exit 0

