#!/bin/bash
######################################################################################
# The goal of this script is to permit to do backups, restaurations, to list and #
# delete the backups. The script facilitates the use of the repozo.py script given #
# with Zope. #
# Author: Francois Birot #
######################################################################################
#######################################################################################
# INFORMATION #
#######################################################################################
PYTHON_BIN="/zope/bin/python"
PYTHON_DIRECTORY="/zope/lib/python"
REPOZO_SCRIPT="/zope/bin/repozo.py"
ZOPE_DATABASE="/zope/production/server/var/Data.fs"
PRODUCTS_DIRECTORY="/zope/production/server/Products"
BACKUP_DIRECTORY="/zope/backups"
ZOPE_USER="zope"
UTC=-4 # The local time is UTC -04:00
#######################################################################################
# DEFAULT OPTIONS #
#######################################################################################
VERBOSE="false" # Don't display anything
MOVE_CURRENT_DATAFS="false" # Don't backup the current Data.fs before restoring
#######################################################################################
# This function checks if the verbose mode is activated and prints the first #
# parameter given to the function #
#######################################################################################
function print_message()
{
if [[ $VERBOSE == "yes" ]]; then
echo "--> $1"
fi
}
#######################################################################################
# This function maintains a list of parameters to give to the repozo.py script #
#######################################################################################
function add_option()
{
if [[ -z "$OPTIONS" ]]; then
OPTIONS="-$1"
else
OPTIONS=$OPTIONS" -$1"
fi
}
#######################################################################################
# This function permits to delete a backup. It requires the basename of the backup as #
# the first parameter #
#######################################################################################
function delete_backup()
{
# If the backup exists, remove it
if [[ -f $BACKUP_DIRECTORY/$1 ]]; then
print_message "Removing $BACKUP_DIRECTORY/$1"
rm $BACKUP_DIRECTORY/$1
# If $1 equals "filename.ext", dat_file will be equals to "filename.dat"
dat_file=${1/${1##*.}/dat}
# If the dat file corresponding to the backup exists, remove it
if [[ -f $BACKUP_DIRECTORY/$dat_file ]]; then
print_message "Removing $BACKUP_DIRECTORY/$dat_file"
rm $BACKUP_DIRECTORY/$dat_file
fi
else
print_message "The backup $1 doesn't exist"
fi
}
#######################################################################################
# This function permit to display a size of a file in GB, MB, KB or B depending of it #
# The function requires one argument: the size to format and display #
#######################################################################################
function echo_size()
{
SCALE=2 # Number of figures after the point
if [[ $1 -gt $((1024*1024*1024)) ]]; then # If the size is greater than a GigaByte
SIZE_UNIT="GB"
SIZE=`echo "scale=$SCALE; $1/$((1024*1024*1024))" | bc -l`
elif [[ $1 -gt $((1024*1024)) ]]; then # If the size is greater than a MegaByte
SIZE_UNIT="MB"
SIZE=`echo "scale=$SCALE; $1/$((1024*1024))" | bc -l`
elif [[ $1 -gt $((1024)) ]]; then # If the size is greater than a KiloByte
SIZE_UNIT="KB"
SIZE=`echo "scale=$SCALE; $1/$((1024))" | bc -l`
else # If the size is lower than a KiloByte
SIZE_UNIT="B"
fi
echo -n $SIZE $SIZE_UNIT
}
#######################################################################################
# This function permits to display the date parsing the name of the backup #
#######################################################################################
function echo_date_from_name()
{
tab[1]="Jan"
tab[2]="Feb"
tab[3]="Mar"
tab[4]="Apr"
tab[5]="May"
tab[6]="Jun"
tab[7]="Jul"
tab[8]="Aug"
tab[9]="Sep"
tab[10]="Oct"
tab[11]="Nov"
tab[12]="Dec"
YEAR=`echo $1 | cut -d '-' -f 1`
MONTH=`echo $1 | cut -d '-' -f 2`
DAY=`echo $1 | cut -d '-' -f 3`
HOUR=`echo $1 | cut -d '-' -f 4`
HOUR=$(((24+HOUR+UTC)%24))
MIN=`echo $1 | cut -d '-' -f 5`
echo -n ${tab[$MONTH]} $DAY $YEAR $HOUR:$MIN
}
#######################################################################################
# This functions lists the backups found in $BACKUP_DIRECTORY #
#######################################################################################
function list_backups()
{
i=1
for DATABASE_FILE in `find $BACKUP_DIRECTORY -name "*.fs" -o -name "*.fsz" -o -name "*.deltafs" -o -name "*.deltafsz" | sort -rM`; do
SIZE=$(stat -c "%s" $DATABASE_FILE)
NAME=`basename $DATABASE_FILE`
echo -ne "\t$i) "
echo_date_from_name $NAME
echo -n " "
echo_size $SIZE
echo -n " ($NAME : "
if [[ ${NAME##*.} == "deltafs" || ${NAME##*.} == "deltafsz" ]]; then
echo "INCREMENTAL)"
else
echo "FULL)"
fi
((i++))
done
}
#######################################################################################
# This function displays some help about how to use the backup script #
#######################################################################################
function echo_help()
{
echo ""
echo -e "\t***Zope Backup Script***"
echo ""
echo -e "\tParameters:"
echo -e "\t[-h] \tDisplays this help"
echo -e "\t[-F] \tDoes a full backup"
echo -e "\t[-I] \tDoes an incremental backup if an old backup is found, else it does a full backup."
echo -e "\t[-D <backup filename>] \tDelete a specific backup file (Don't give the path, only the filename)"
echo -e "\t[-R <backup filename>] \tRestores a specific backup file (Don't give the path, only the filename)"
echo -e "\t[-m] \tBackup the current Data.fs before restoring (the parameter -R has to be specified)"
echo -e "\t[-l] \tLists the backup files"
echo -e "\t[-z] \tCompress with gzip the backup files"
echo -e "\t[-v] \tVerbose mode"
}
#######################################################################################
# BEGINING OF THE SCRIPT #
#######################################################################################
# The repozo.py needs the PYTHONPATH environment variable to be set
export PYTHONPATH=$PYTHON_DIRECTORY
# The action variable can be changed depending of the parameters, to "backup", "suppression" or "restoration"
ACTION="nothing"
while getopts ":hlvzmFIR:D:" PARAM; do
case $PARAM in
h)
echo_help
exit 0
;;
l)
list_backups
exit 0
;;
F)
ACTION="backup"
INCREMENTAL_BACKUP="false"
;;
I)
ACTION="backup"
INCREMENTAL_BACKUP="true"
;;
R)
ACTION="restauration"
BACKUP_FILE=$OPTARG
;;
D)
ACTION="suppression"
BACKUP_FILE=$OPTARG
;;
m)
MOVE_CURRENT_DATAFS="yes"
;;
v)
VERBOSE="yes"
add_option "v"
;;
z)
add_option "z"
;;
*)
echo "Try '$0 -h' to get help"
exit 1
;;
esac
done && shift $(($OPTIND - 1))
if [[ $ACTION == "nothing" ]]; then
echo_help
exit 1
fi
if [[ $ACTION == "backup" ]]; then
if [[ -z $INCREMENTAL_BACKUP ]]; then
echo "You have to specify the type of backup to do (full or incremental)"
exit 1
elif [[ $INCREMENTAL_BACKUP == "false" ]]; then
add_option "F"
fi
# We do the backup using the repozo.py script
print_message "Backing up $ZOPE_DATABASE"
$PYTHON_BIN $REPOZO_SCRIPT $OPTIONS -B -r $BACKUP_DIRECTORY -f $ZOPE_DATABASE
elif [[ $ACTION == "restauration" ]]; then
# If there is an actual Data.fs and the "-m" parameter is specified, we backup the current Data.fs
if [[ -f $ZOPE_DATABASE && $MOVE_CURRENT_DATAFS == "yes" ]]; then
DATE_FORMATED=`date --utc '+%Y-%m-%d-%H-%M-%S'`
FS_FILE=$BACKUP_DIRECTORY/$DATE_FORMATED.fs
DAT_FILE=$BACKUP_DIRECTORY/$DATE_FORMATED.dat
# We move the actual Data.fs to the backup directory
print_message "Moving $ZOPE_DATABASE to $FS_FILE"
mv $ZOPE_DATABASE $FS_FILE
# We now create the .dat file in order that repozo.py can use this Data.fs later, as a real backup
print_message "Calculating the MD5 sum of $FS_FILE"
echo -n "$FS_FILE 0 `ls -l $FS_FILE | cut -d ' ' -f 5`" > $DAT_FILE
echo " `md5sum $FS_FILE | cut -d ' ' -f 1`" >> $DAT_FILE
fi
# We now retore the backup file
print_message "Restoring $BACKUP_DIRECTORY/$BACKUP_FILE"
$PYTHON_BIN $REPOZO_SCRIPT $OPTIONS -R -D $BACKUP_FILE -r $BACKUP_DIRECTORY -o $ZOPE_DATABASE
# We set $ZOPE_USER as the owner and the group of the Data.fs
print_message "Changing the permissions of $ZOPE_DATABASE"
chown $ZOPE_USER:$ZOPE_USER $ZOPE_DATABASE
elif [[ $ACTION == "suppression" ]]; then
delete_backup $BACKUP_FILE
fi