Difference between revisions of "Open Source Edition Backup Procedure"

(Adding Unsupported template)
 
(37 intermediate revisions by 16 users not shown)
Line 1: Line 1:
{{Unsupported}}
+
{{BC|Community Sandbox}}
 
+
__FORCETOC__
If you wish to have a more automated backup feature, you should try the [Network Version of Zimbra.]
+
<div class="col-md-12 ibox-content">
 +
= Open Source Edition Backup Procedure=
 +
{{KB|{{Unsupported}}|{{ZCS 5.0}}|{{ZCS 4.5}}|}}
 +
{{Archive}}
 +
If you wish to have a more automated backup feature, you should try the Network Version of Zimbra.
  
 
==Backup Scripts==
 
==Backup Scripts==
Line 26: Line 30:
 
  zimbra_vol_fs=PUT_ZIMBRA_FILE_SYSTEM_TYPE_HERE
 
  zimbra_vol_fs=PUT_ZIMBRA_FILE_SYSTEM_TYPE_HERE
 
   
 
   
 +
# lvcreate and lvremove commands path -
 +
lvcreate_cmd=`which lvcreate`
 +
lvremove_cmd=`which lvremove`
 +
 
 
  # Do not change anything beyond this point
 
  # Do not change anything beyond this point
 
  #########################################
 
  #########################################
Line 50: Line 58:
 
  # Create a logical volume called ZimbraBackup
 
  # Create a logical volume called ZimbraBackup
 
  say $GREEN"Creating a LV called ZimbraBackup:"$PURPLE
 
  say $GREEN"Creating a LV called ZimbraBackup:"$PURPLE
  /usr/sbin/lvcreate -L1000M -s -n ZimbraBackup /dev/$vol_group/$zimbra_vol
+
  $lvcreate_cmd -L1000M -s -n ZimbraBackup /dev/$vol_group/$zimbra_vol
 
   
 
   
 
  # Create a mountpoint to mount the logical volume to
 
  # Create a mountpoint to mount the logical volume to
 
  say $GREEN"Creating a mountpoint for the LV..."
 
  say $GREEN"Creating a mountpoint for the LV..."
 +
# WARNING: this is insecure!
 
  mkdir -p /tmp/ZimbraBackup
 
  mkdir -p /tmp/ZimbraBackup
 
   
 
   
 
  # Mount the logical volume to the mountpoint
 
  # Mount the logical volume to the mountpoint
 
  say $GREEN"Mounting the LV..."
 
  say $GREEN"Mounting the LV..."
 +
# WARNING: remove nouuid option if the filesystem is not formatted as XFS !!! 
 
  mount -t $zimbra_vol_fs -o nouuid,ro /dev/$vol_group/ZimbraBackup /tmp/ZimbraBackup/
 
  mount -t $zimbra_vol_fs -o nouuid,ro /dev/$vol_group/ZimbraBackup /tmp/ZimbraBackup/
 
   
 
   
 
  # Start the Zimbra services
 
  # Start the Zimbra services
 
  say $CYAN"Starting the Zimbra services..."
 
  say $CYAN"Starting the Zimbra services..."
 +
# WARNING: it's safer not to put this command in background
 
  /etc/init.d/zimbra start &
 
  /etc/init.d/zimbra start &
 
   
 
   
Line 76: Line 87:
 
  say $GREEN"Unmounting and removing the LV."$PURPLE
 
  say $GREEN"Unmounting and removing the LV."$PURPLE
 
  umount /tmp/ZimbraBackup/
 
  umount /tmp/ZimbraBackup/
  /usr/sbin/lvremove --force /dev/$vol_group/ZimbraBackup
+
  $lvremove_cmd --force /dev/$vol_group/ZimbraBackup
 
   
 
   
 
  # Done!
 
  # Done!
Line 82: Line 93:
 
  say $GREEN"Backup ended at "$RED"`date`"$GREEN".\e[0m"
 
  say $GREEN"Backup ended at "$RED"`date`"$GREEN".\e[0m"
  
====More elaborated script, using LVM and rsync====
+
===More elaborated script, using LVM and rsync===
Download at https://support.ginsys.be/svn/zimbrackup/ <br />
+
More info at https://github.com/sergevanginderachter/sysadmintools/tree/master/zimbrackup <br />
Send feedback to Serge van Ginderachter <svg@ginsys.be> <br />
+
 
 +
===Yet another backup script, using LVM and duplicity===
 +
 
 +
The previous examples use ''tar'' and ''rsync'' respectively. Both have disadvantages:
 +
 
 +
* they don't support incremental backups
 +
* you need to do additional scripting to encrypt the backup and purging of old backups
 +
 
 +
I modified the first script to use duplicity instead of plain ''tar''. This way you have the flexibility to use any protocol you like (scp, rsync, ftp) to upload the backup, you don't have to worry about old backups and you can save a lot of disk space!
 +
 
 +
Get the script: http://www.nervous.it/2007/01/zimbra-lvm-backup-with-duplicity-volume/
 +
Get duplicity: http://duplicity.nongnu.org/
  
 
===The Perl way of doing it (without LVM)===
 
===The Perl way of doing it (without LVM)===
Line 566: Line 588:
 
The following script can be called from the command line or crontab, and relies only on rsync, tar, and a scriptable ftp client.  I used [http://www.ncftp.com ncftp] but you can use others and modify the syntax accordingly.  This script was written and tested in Ubuntu 6.06 LTS server.  I cannot confirm if it requires any modification to work in other distros but would appreciate feedback if necessary to make it more general.
 
The following script can be called from the command line or crontab, and relies only on rsync, tar, and a scriptable ftp client.  I used [http://www.ncftp.com ncftp] but you can use others and modify the syntax accordingly.  This script was written and tested in Ubuntu 6.06 LTS server.  I cannot confirm if it requires any modification to work in other distros but would appreciate feedback if necessary to make it more general.
 
<pre>
 
<pre>
 +
#!/bin/bash
 +
 +
# Zimbra Backup Script
 +
# Requires ncftp to run
 +
# This script is intended to run from the crontab as root
 +
# Date outputs and su vs sudo corrections by other contributors, thanks, sorry I don't have names to attribute!
 +
# Free to use and free of any warranty!  Daniel W. Martin, 5 Dec 2008
 +
 +
 +
# Outputs the time the backup started, for log/tracking purposes
 +
echo Time backup started = $(date +%T)
 +
before="$(date +%s)"
 +
 +
# Live sync before stopping Zimbra to minimize sync time with the services down
 +
# Comment out the following line if you want to try single cold-sync only
 +
rsync -avHK --delete /opt/zimbra/ /backup/zimbra
 +
 +
# which is the same as: /opt/zimbra /backup
 +
# Including --delete option gets rid of files in the dest folder that don't exist at the src
 +
# this prevents logfile/extraneous bloat from building up overtime.
 +
 +
# Now we need to shut down Zimbra to rsync any files that were/are locked
 +
# whilst backing up when the server was up and running.
 +
before2="$(date +%s)"
 +
 +
# Stop Zimbra Services
 +
su - zimbra -c"/opt/zimbra/bin/zmcontrol stop"
 +
sleep 15
 +
 +
# Kill any orphaned Zimbra processes
 +
ORPHANED=`ps -u zimbra -o "pid="` && kill -9 $ORPHANED
 +
 +
# Only enable the following command if you need all Zimbra user owned
 +
# processes to be killed before syncing
 +
# ps auxww | awk '{print $1" "$2}' | grep zimbra | kill -9 `awk '{print $2}'`
 +
 +
# Sync to backup directory
 +
rsync -avHK --delete /opt/zimbra/ /backup/zimbra
 +
 +
# Restart Zimbra Services
 +
su - zimbra -c "/opt/zimbra/bin/zmcontrol start"
 +
 +
# Calculates and outputs amount of time the server was down for
 +
after="$(date +%s)"
 +
elapsed="$(expr $after - $before2)"
 +
hours=$(($elapsed / 3600))
 +
elapsed=$(($elapsed - $hours * 3600))
 +
minutes=$(($elapsed / 60))
 +
seconds=$(($elapsed - $minutes * 60))
 +
echo Server was down for: "$hours hours $minutes minutes $seconds seconds"
 +
 +
# Create a txt file in the backup directory that'll contains the current Zimbra
 +
# server version. Handy for knowing what version of Zimbra a backup can be restored to.
 +
su - zimbra -c "zmcontrol -v > /backup/zimbra/conf/zimbra_version.txt"
 +
# or examine your /opt/zimbra/.install_history
 +
 +
# Display Zimbra services status
 +
echo Displaying Zimbra services status...
 +
su - zimbra -c "/opt/zimbra/bin/zmcontrol status"
 +
 +
# Create archive of backed-up directory for offsite transfer
 +
# cd /backup/zimbra
 +
umask 0177
 +
tar -zcvf /tmp/mail.backup.tgz -C /backup/zimbra .
 +
 +
# Transfer file to backup server
 +
ncftpput -u <username> -p <password> <ftpserver> /<desired dest. directory> /tmp/mail.backup.tgz
 +
 +
rm /tmp/mail.backup.tgz
 +
 +
# Outputs the time the backup finished
 +
echo Time backup finished = $(date +%T)
 +
 +
# Calculates and outputs total time taken
 +
after="$(date +%s)"
 +
elapsed="$(expr $after - $before)"
 +
hours=$(($elapsed / 3600))
 +
elapsed=$(($elapsed - $hours * 3600))
 +
minutes=$(($elapsed / 60))
 +
seconds=$(($elapsed - $minutes * 60))
 +
echo Time taken: "$hours hours $minutes minutes $seconds seconds"
 +
</pre>
 +
 +
One further note:  I have observed some odd behavior in this and other scripts that, when run from the command line work flawlessly, but when run from crontab the script may get ahead of itself and, for example, try to ftp the file before tar is done creating it; resulting in a useless backup.  Loading the script into crontab with the parameters to create a log file, for example
 +
. /etc/zimbra.backup > /temp/zbackup.log 2>&1
 +
seems to solve this problem (while creating the log, or showing the output on the screen, the script seems to follow the sequence more carefully), while giving you a line-by-line record of the backup procedure.  In my installation with just over 3GB backed up, the logfile is 2.5 mb and is overwritten each night.
 +
 +
'''NB''' You may find that using su on your operating system has problems and some services don't start or stop correctly. If that's the case use 'sudo -u zimbra' in the following format for the commands:
 +
sudo -u zimbra zmcontrol start
 +
 +
===A Simple Shell Script Method like above, but with rsync over ssh ===
 +
 
  #!/bin/bash
 
  #!/bin/bash
 
   
 
   
 
  # Zimbra Backup Script
 
  # Zimbra Backup Script
  # Requires ncftp to run
+
  # Requires that you have ssh-keys: https://help.ubuntu.com/community/SSHHowto#Public%20key%20authentication
 
  # This script is intended to run from the crontab as root
 
  # This script is intended to run from the crontab as root
  # Free to use and free of any warranty!  Daniel W. Martin, 9 Sept 2007
+
# Date outputs and su vs sudo corrections by other contributors, thanks, sorry I don't have names to attribute!
 +
  # Free to use and free of any warranty!  Daniel W. Martin, 5 Dec 2008
 +
## Adapted for rsync over ssh instead of ncftp by Ace Suares, 24 April 2009 (Ubuntu 6.06 LTS)
 +
 +
# the destination directory for local backups
 +
DESTLOCAL=/backup/backup-zimbra
 +
# the destination for remote backups
 +
DESTREMOTE="yourserver:/backup/backup-zimbra"
 +
 +
# Outputs the time the backup started, for log/tracking purposes
 +
echo Time backup started = $(date +%T)
 +
before="$(date +%s)"
 +
# a backup dir on the local machine. This will fill up over time!
 +
BACKUPDIR=$DESTLOCAL/$(date +%F-%H-%M-%S)
 
   
 
   
 
  # Live sync before stopping Zimbra to minimize sync time with the services down
 
  # Live sync before stopping Zimbra to minimize sync time with the services down
 
  # Comment out the following line if you want to try single cold-sync only
 
  # Comment out the following line if you want to try single cold-sync only
  rsync -avHK --delete /opt/zimbra/ /backup/zimbra
+
  rsync -avHK --delete --backup --backup-dir=$BACKUPDIR /opt/zimbra/ $DESTLOCAL/zimbra
 
+
 
  # which is the same as: /opt/zimbra /backup  
 
  # which is the same as: /opt/zimbra /backup  
 
  # Including --delete option gets rid of files in the dest folder that don't exist at the src  
 
  # Including --delete option gets rid of files in the dest folder that don't exist at the src  
 
  # this prevents logfile/extraneous bloat from building up overtime.
 
  # this prevents logfile/extraneous bloat from building up overtime.
 
+
# the backupdir will hold all files that changed or where deleted during the previous backup
 +
 +
# Now we need to shut down Zimbra to rsync any files that were/are locked
 +
# whilst backing up when the server was up and running.
 +
before2="$(date +%s)"
 +
 
  # Stop Zimbra Services
 
  # Stop Zimbra Services
  sudo -u zimbra /opt/zimbra/bin/zmcontrol stop
+
  /etc/init.d/zimbra stop
  sleep 20
+
#su - zimbra -c"/opt/zimbra/bin/zmcontrol stop"
 +
  #sleep 15
 +
# Kill any orphaned Zimbra processes
 +
#kill -9 `ps -u zimbra -o "pid="`
 +
pkill -9 -u zimbra
 +
 +
# Only enable the following command if you need all Zimbra user owned
 +
# processes to be killed before syncing
 +
# ps auxww | awk '{print $1" "$2}' | grep zimbra | kill -9 `awk '{print $2}'`
 
   
 
   
 
  # Sync to backup directory
 
  # Sync to backup directory
  rsync -avHK --delete /opt/zimbra/ /backup/zimbra
+
  rsync -avHK --delete --backup --backup-dir=$BACKUPDIR /opt/zimbra/ $DESTLOCAL/zimbra
 
+
 
  # Restart Zimbra Services
 
  # Restart Zimbra Services
  sudo -u zimbra /opt/zimbra/bin/zmcontrol start
+
  #su - zimbra -c "/opt/zimbra/bin/zmcontrol start"
 
+
/etc/init.d/zimbra start
  # Create a txt file in the backup directory that'll contain the current Zimbra
+
 +
# Calculates and outputs amount of time the server was down for
 +
after="$(date +%s)"
 +
elapsed="$(expr $after - $before2)"
 +
hours=$(($elapsed / 3600))
 +
elapsed=$(($elapsed - $hours * 3600))
 +
minutes=$(($elapsed / 60))
 +
seconds=$(($elapsed - $minutes * 60))
 +
echo SERVER WAS DOWN FOR: "$hours hours $minutes minutes $seconds seconds"
 +
 +
  # Create a txt file in the backup directory that'll contains the current Zimbra
 
  # server version. Handy for knowing what version of Zimbra a backup can be restored to.
 
  # server version. Handy for knowing what version of Zimbra a backup can be restored to.
  sudo -u zimbra zmcontrol -v > /backup/zimbra/conf/zimbra_version.txt
+
  # su - zimbra -c "zmcontrol -v > $DESTLOCAL/zimbra/conf/zimbra_version.txt"
 
  # or examine your /opt/zimbra/.install_history
 
  # or examine your /opt/zimbra/.install_history
 
   
 
   
  # Create archive of backed-up directory for offsite transfer
+
  # Display Zimbra services status
  # cd /backup/zimbra
+
echo Displaying Zimbra services status...
  tar -zcvf /tmp/mail.backup.tgz -C /backup/zimbra .
+
su - zimbra -c "/opt/zimbra/bin/zmcontrol status"
 +
  # /etc/init.d/zimbra status # seems not to work
 +
# backup the backup dir (but not the backups of the backups) to remote
 +
  rsync -essh -avHK --delete-during $DESTLOCAL/zimbra $DESTREMOTE
 +
 +
# Outputs the time the backup finished
 +
echo Time backup finished = $(date +%T)
 +
 +
# Calculates and outputs total time taken
 +
after="$(date +%s)"
 +
elapsed="$(expr $after - $before)"
 +
hours=$(($elapsed / 3600))
 +
elapsed=$(($elapsed - $hours * 3600))
 +
minutes=$(($elapsed / 60))
 +
seconds=$(($elapsed - $minutes * 60))
 +
echo Time taken: "$hours hours $minutes minutes $seconds seconds"
 
   
 
   
  # Transfer file to backup server
+
  # end
ncftpput -u <username> -p <password> <ftpserver> /<desired dest. directory> /tmp/mail.backup.tgz
 
</pre>
 
One further note:  I have observed some odd behavior in this and other scripts that, when run from the command line work flawlessly, but when run from crontab the script may get ahead of itself and, for example, try to ftp the file before tar is done creating it; resulting in a useless backup.  Loading the script into crontab with the parameters to create a log file, for example
 
. /etc/zimbra.backup > /temp/zbackup.log 2>&1
 
seems to solve this problem (while creating the log, or showing the output on the screen, the script seems to follow the sequence more carefully), while giving you a line-by-line record of the backup procedure.  In my installation with just over 3GB backed up, the logfile is 2.5 mb and is overwritten each night.
 
 
 
'''NB''' You may find that using sudo on your operating system has problems and some services don't start correctly. If that's the case use 'su -' in the following format for the commands:
 
su - zimbra -c "zmcontrol start"
 
 
 
  
 
===Backup Shell Script with Compressed & Encrypted Archives===
 
===Backup Shell Script with Compressed & Encrypted Archives===
Line 626: Line 782:
  
  
You can follow the development and find the latest info about usage and so on in the zimbra forum under the thread "Yet Another Backup Script Community Version"
+
You can follow the development and find the latest info about usage and so on in the zimbra forum under the thread "[[http://www.zimbra.com/forums/administrators/15275-yet-another-backup-script-community-version.html Yet Another Backup Script Community Version]]"
 
 
 
To download a current version of this script go to the forum thread there you will find a link to the file in the first post.
 
To download a current version of this script go to the forum thread there you will find a link to the file in the first post.
 
If you need any help you can contact me in the forum, I would be happy to help!
 
If you need any help you can contact me in the forum, I would be happy to help!
Line 654: Line 809:
 
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 
# THE USE OF THIS DOCUMENT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
# THE USE OF THIS DOCUMENT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 +
#
 +
# CONTRIBUTORS:
 +
# heinzg of osoffice.de (original author)
 +
# Quentin Hartman of Concentric Sky, qhartman@concentricsky.com (refactor and cleanup)
 
#
 
#
 
# What this script does:
 
# What this script does:
Line 663: Line 822:
 
# 6. Backup archive integrity checks and md5 checksums creation.
 
# 6. Backup archive integrity checks and md5 checksums creation.
 
# 7. Automated DR - Off-site copy of backup archives via ssh.
 
# 7. Automated DR - Off-site copy of backup archives via ssh.
# 8. Install and setup function for needed sofrware (Ubuntu Systems only)
+
# 8. Install and setup function for needed software (Ubuntu Systems only)
 
# 9. Weekly eMail report & eMail on error - including CC address.
 
# 9. Weekly eMail report & eMail on error - including CC address.
 
#
 
#
Line 674: Line 833:
 
#
 
#
 
# What is still to come or needs work on:
 
# What is still to come or needs work on:
# 1. Recover option
+
# 1. Recovery option
 
# 2. Better documentation
 
# 2. Better documentation
#
+
 
#------- CONFIG -------#
+
##------- CONFIG -------#
 
# Edit this part of the script to fit your needs.
 
# Edit this part of the script to fit your needs.
#
 
  
 
#--- Directories ---#
 
#--- Directories ---#
 
# Please add the trailing "/" to directories!
 
# Please add the trailing "/" to directories!
ZM_HOME=/opt/zimbra/
+
ZM_HOME=/opt/zimbra/ # where zimbra lives
SYNC_DIR=/srv/backup/sync/
+
SYNC_DIR=/tmp/fakebackup/ # intermediate dir for hot/cold syncs. must have at least as much free space as ZM_HOME consumes
ARCHIVEDIR=/srv/backup/dars/
+
ARCHIVEDIR=/Backup/zimbra_dars/ # where to store final backups
TOO_MEDIA_DIR=/srv/backup/burn/
+
TO_MEDIA_DIR=/Backup/burn/ # where to put fulls for archiving to media
  
#
 
 
#--- PROGRAM OPTIONS ---#  
 
#--- PROGRAM OPTIONS ---#  
RSYNC_OPTS="-aHK --delete --exclude=*.pid"
+
RSYNC_OPTS="-aHK --delete --exclude=*.pid" # leave these unless you are sure you need something else
  
#
 
 
#--- ARCHIVE NAMES ---#
 
#--- ARCHIVE NAMES ---#
BACKUPNAME="Zimbra_Backup"
+
BACKUPNAME="Zimbra_Backup" # what you want your backups called
BACKUPTYPE_F="FULL" # name prefix to sort between full and diff backups
+
FULL_PREFIX="FULL" # prefix used for full backups
BACKUPTYPE_D="DIFF"
+
DIFF_PREFIX="DIFF" # prefix used for differential backups
BACKUPDATE=`date +%d-%B-%Y`
+
BACKUPDATE=`date +%d-%B-%Y` # date format used in archive names
 +
BACKUPWEEK=`date +%W` # Week prefix used for backup weekly rotation and naming
  
#
 
 
#--- ARCHIVE SIZE ---#
 
#--- ARCHIVE SIZE ---#
# storage media size
+
ARCHIVESIZE="4395M" # storage media size, for full-backup archiving
ARCHIVESIZE="4395M"
 
 
COMPRESS="9" # valid answers are 1 - 9 ( 9 = best )
 
COMPRESS="9" # valid answers are 1 - 9 ( 9 = best )
  
 +
#--- Encryption Options ---#
 
CRYPT="yes" # valid answers are "yes" or "no"
 
CRYPT="yes" # valid answers are "yes" or "no"
PASSDIR=/etc/zmbac/
+
PASSDIR=/etc/`basename $0`/ # the directory the encryption hash is stored in.
PASSFILE="noread"
+
PASSFILE="noread" # the file containing the password hash
  
#
+
#--- Log Settings ---#
#--- EMAIL ADDRESS ---#
+
EMAIL="your@mailaddress.local" # the address to send logs to
EMAIL="admin@localhost"
+
EMAILCC="" # another address to send to
EMAILCC="admin@remotehost"
+
LOG="/var/log/zim_backup.log" # log location
LOG="/var/log/zim_backup.log"
 
  
 
#--- SSH REMOTE DR COPY ---#
 
#--- SSH REMOTE DR COPY ---#
# This option will secure copy you archives to a remote server via 'scp'
+
# This option will secure copy your archives to a remote server via 'scp'
DRCP="yes" # valid answers are "yes" or "no"  
+
DRCP="no" # valid answers are "yes" or "no"  
SSHUSER="heinzg"
+
SSHUSER="you" # recommend creating a user on the remote machine just for transferring backups
REMOTEHOST="172.16.184.1"
+
SSHKEY="rsa" # recommended answers are "rsa" or "dsa" but "rsa1" is also valid.
REMOTEDIR="/tmp/"
+
REMOTEHOST="remote.server.fqdn" # can use IP too
 +
REMOTEDIR="/tmp/" # where you want your backups saved.
  
#--- USE HACKS !?! ---#
+
#--- Use Hacks? ---#
 
# Built in hacks to fix common problems
 
# Built in hacks to fix common problems
 
#Hack to start Stats, even run zmlogprocess if needed
 
#Hack to start Stats, even run zmlogprocess if needed
Line 731: Line 887:
 
# Best you don't change anything from here on,  
 
# Best you don't change anything from here on,  
 
# ONLY EDIT IF YOU KNOW WHAT YOU ARE DOING
 
# ONLY EDIT IF YOU KNOW WHAT YOU ARE DOING
#
 
#
 
 
# Check if Zimbra install dir is there
 
if [ ! -d $ZM_HOME ]
 
then
 
    echo "$ZM_HOME not found!"
 
    exit 1
 
fi
 
 
# Check the script is being run by root, or die.
 
ROOT_UID=0
 
if [ "$UID" -ne "$ROOT_UID" ]
 
then
 
  echo "Run script as "root"."
 
  echo
 
  exit 1
 
fi
 
 
# Create Log file
 
touch $LOG
 
 
# Script Timer
 
STARTTIME=(`date +%s`)
 
 
# Week prefix used for backup weekly rotation and naming
 
BACKUPWEEK=`date +%W`
 
 
# Finding out who is the zimbra proc user
 
ZM_USER=`ps -ef | grep "$ZM_HOME" | grep "java" | grep -v "zmmailboxdmgr" | awk '{print $1}' | head -n 1`
 
if [ -z $ZM_USER ]
 
then
 
    echo "Unable to determan the zimbra user"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
    elif [ $ZM_USER = "root" ]
 
    then
 
echo "Zimbra user should never be root! I'll die now..."
 
# send email....
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
fi
 
 
# Location of Zimbra's PID files
 
STATPIDBASE="$ZM_HOME""zmstat/pid/"
 
 
 
case $1 in
 
    -V | --version)
 
    echo
 
    echo "Version 1.02"
 
    echo "first published Feb 08"
 
    echo
 
    echo "Change Log March 08:"
 
    echo "- Use the su command insted if sudo to stop and start services"
 
    echo "- Using shutdown insted of stop with zmcontrol"
 
    echo "- DATE_VERSION.txt now contains date and version and is created with full backups"
 
    echo "- Built in some more checks"
 
    echo "- eMail notification on error"
 
    echo "- Documentation - Added more comments"
 
    echo "- Dar archive is now built from current dir"
 
    echo "- Stats hack to make sure stats is starting again"
 
    echo "- 260 more lines of code... and who knows how many bugs"
 
    echo
 
    ;;
 
 
    -h | --help)
 
    echo
 
    echo "Configure the "CONFIG" part of the script to suit your needs."
 
    echo
 
    echo "USAGE:    -h or --help for help & usage."
 
    echo "          -f or --full for Full backup."
 
    echo "          -d or --diff for Diff backup."
 
    echo "          --INSTALL    for script install and setup."
 
    echo
 
    echo "Usage with cron, e.g."
 
    echo "0 3 * * 1    /bin/bash    /root/zmbac.sh -f > $LOG 2>&1"
 
    echo "0 3 * * 2-7  /bin/bash    /root/zmbac.sh -d >> $LOG 2>&1"
 
    echo
 
    ;;
 
 
    --INSTALL)
 
   
 
    # Check for configured Directories or Create them
 
   
 
    if [ ! -d $SYNC_DIR ]
 
    then
 
    echo
 
        echo "$SYNC_DIR not found!"
 
echo -n "Create $SYNC_DIR "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
    mkdir -vp -m 600 $SYNC_DIR
 
else
 
    echo "Please check script Config, and try again"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
fi
 
    fi
 
 
    if [ ! -d $ARCHIVEDIR ]
 
    then
 
    echo
 
echo "$ARCHIVEDIR not found!"
 
echo -n "Create $ARCHIVEDIR "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
mkdir -vp -m 600 $ARCHIVEDIR
 
else
 
    echo "Please check script Config, and try again"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
fi
 
    fi
 
 
    if [ ! -d $TOO_MEDIA_DIR ]
 
    then
 
    echo
 
    echo "directory $TOO_MEDIA_DIR not found!"
 
echo -n "Create $TOO_MEDIA_DIR "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
    mkdir -vp -m 600 $TOO_MEDIA_DIR
 
else
 
    echo "Please check script Config, and try again"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
fi
 
    fi
 
   
 
    # Check for needed software or try install it
 
   
 
    MAILX=`whereis mailx | awk '{print $2}'`
 
    if [ ! -e "$MAILX" ]
 
    then
 
    echo
 
echo "'mailx' is not installed!"
 
echo
 
echo "For a "Howto" install mailx without postfix please visit the link below"
 
echo "http://www.zimbra.com/forums/administrators/13528-sending-email-comand-line-logwatch-ubuntu-6-06-a.html#post70636"
 
echo
 
echo "Should I "try" install this for you?"
 
echo
 
echo "!! Only say yes if you are running Ubuntu!!"
 
echo
 
echo -n "install "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
            echo
 
    echo "Downloading "mta-dummy" package to "/tmp""
 
    cd /tmp
 
    wget -v -S -c -t 40 --random-wait -T 60 http://ubuntu.lnix.net/misc/mta-dummy/mta-dummy_1.0_all.deb
 
    if [ "$?" -ne "0" ]
 
    then
 
            echo "Had some form of problem getting the mta-dummy package... ask for help in the forums"
 
echo
 
exit 1
 
    fi
 
        echo
 
        dpkg -i mta-dummy_1.0_all.deb
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo "Had some form of problem getting installing the mta-dummy package... ask for help in the forums"
 
            echo
 
            exit 1
 
        fi
 
 
        echo
 
        echo
 
        apt-get -y install mailx
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo "Had some form of problem installing 'mailx'... ask for help in the forums"
 
            echo
 
            exit 1
 
        fi
 
        echo
 
        echo "Writing config file "/etc/mail.rc""
 
echo "set sendmail=$ZM_HOME"postfix/sbin/sendmail"" >> /etc/mail.rc
 
        else
 
            echo "This script would like to send you a mail or two... so please install a dummy mta for your Distro"
 
    echo
 
    exit 1
 
fi
 
    fi
 
 
    UUENCODE=`whereis uuencode | awk '{print $2}'`
 
    if [ ! -e "$UUENCODE" ]
 
    then
 
    echo
 
echo "'uuencode' is not installed!"
 
echo
 
echo "Should I "try" install 'uuencode' for you?"
 
echo
 
echo "!! Only say yes if you are running Ubuntu!!"
 
echo -n "install "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
    apt-get -y install sharutils
 
    if [ "$?" -ne "0" ]
 
    then
 
            echo "Had some form of problem installing "sharutils"... ask for help in the forums"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
fi
 
    fi
 
 
    DAR_BIN=`whereis dar | awk '{print $2}'`
 
    if [ ! -e "$DAR_BIN" ]
 
    then
 
    echo
 
echo "'dar' is not installed!"
 
echo
 
echo "Should I "try" install 'dar' for you?"
 
echo
 
echo "!! Only say yes if you are running Ubuntu!!"
 
echo -n "install "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
    apt-get -y install dar
 
    if [ "$?" -ne "0" ]
 
    then
 
            echo "Had some form of problem installing "dar"... ask for help in the forums"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
fi
 
    fi
 
 
    SSH_BIN=`whereis ssh | awk '{print $2}'`
 
    if [ ! -e "$SSH_BIN" ]
 
    then
 
    echo
 
echo "Please install "ssh"!"
 
echo
 
echo "Should I "try" install a 'ssh client & server' for you?"
 
echo
 
echo "!! Only say yes if you are running Ubuntu!!"
 
echo -n "install "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
    apt-get -y install openssh-server
 
    if [ "$?" -ne "0" ]
 
    then
 
            echo "Had some form of problem installing "openssh-server"... ask for help in the forums"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
echo
 
exit 1
 
    fi
 
fi
 
    fi
 
   
 
    if [ $CRYPT = "yes" ]
 
    then
 
    if [ ! -d "$PASSDIR" ]
 
    then
 
        echo "Create $PASSDIR"
 
        echo -n "install "y" or "n": "
 
        read ANSWER
 
    if [ $ANSWER = "y" ]
 
    then
 
        mkdir -vp -m 600 $PASSDIR
 
        echo "done"
 
        echo
 
    else   
 
    echo "Please check script Config, and try again"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
    fi
 
fi
 
    fi
 
 
if [ ! -e "$PASSFILE" ]   
 
then
 
        echo "Create $PASSFILE"
 
        echo -n "install "y" or "n": "
 
        read ANSWER
 
        if [ $ANSWER = "y" ]
 
    then
 
        touch "$PASSDIR""$PASSFILE"
 
        chmod 600 "$PASSDIR""$PASSFILE"
 
        echo "'G'enerate or 'E'nter a secure passphrase"
 
        echo -n "please enter G or E: "
 
        read ANSWER
 
        if [ "$ANSWER" = "G" ]
 
        then
 
            openssl rand -base64 48 -out "$PASSDIR""$PASSFILE" 2>/dev/null
 
        else
 
            echo -n "Enter a secure passphrase: "
 
            read PASSPHRASE
 
            echo $PASSPHRASE > "$PASSDIR""$PASSFILE"
 
            echo "done"
 
            echo
 
        fi
 
    else   
 
        echo "Please check script Config, and try again"
 
        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
        exit 1
 
    fi
 
fi
 
   
 
    echo
 
    if [ $DRCP = "yes" ]
 
    then
 
    echo
 
echo "For 'scp' to work, you have to have setup PKI authentication (passwork less login)"
 
echo "Should I try setup this for you?"
 
echo -n "install "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
    ssh-copy-id "$SSHUSER"@"$REMOTEHOST"
 
    if [ "$?" -ne "0" ]
 
    then
 
            echo "$?"
 
echo -n "Create ssh ID? "y" or "n": "
 
read ANSWER
 
if [ $ANSWER = "y" ]
 
then
 
    echo "Please except defaults, and NO 'passphrase' !!"
 
    ssh-keygen
 
    echo
 
    echo "copying your ID to $REMOTEHOST"
 
    echo "please enter your '$SSHUSER' user password on '$REMOTEHOST' at the prompt"
 
    ssh-copy-id -i /root/.ssh/id_rsa "$SSHUSER"@"$REMOTEHOST"
 
fi
 
    fi
 
fi
 
    fi
 
 
    echo
 
    echo "Install cronjob to automate the nightly backups"
 
    echo -n "install "y" or "n": "
 
    read ANSWER
 
    if [ $ANSWER = "y" ]
 
    then
 
        crontab -l > $HOME/.crontab.save
 
        echo "Setting the time when to start the backup cycle"
 
        echo -n "At what hour? 0-23: "
 
        read HOUR
 
echo
 
echo -n "and what minute do you want the backup to start? 0-59: "
 
read MINUTE
 
echo
 
echo "path to script e.g. /root/scripts"
 
read SPATH
 
echo "" >> $HOME/.crontab.save
 
        echo "$MINUTE $HOUR * * 1    /bin/bash    $SPATH/zmbac.sh -f > $LOG 2>&1" >> $HOME/.crontab.save
 
        echo "$MINUTE $HOUR * * 2-7  /bin/bash    $SPATH/zmbac.sh -d >> $LOG 2>&1" >> $HOME/.crontab.save
 
        echo "" >> $HOME/.crontab.save
 
        crontab $HOME/.crontab.save
 
        rm $HOME/.crontab.save
 
        echo
 
        crontab -l
 
        echo
 
        echo "Done setting up crontab"
 
        echo
 
    fi
 
   
 
    ;;
 
 
    -f | --full)
 
    echo
 
    echo "      Full Backup started at: `date +%H:%M`"
 
    echo
 
    DAR_BIN=`whereis dar | awk '{print $2}'`
 
    if [ ! -e "$DAR_BIN" ]
 
    then
 
    echo "Please install "dar"!"
 
echo "Try running the script with --INSTALL"
 
exit 1
 
    fi
 
 
    MAILX=`whereis mailx | awk '{print $2}'`
 
    if [ ! -e "$MAILX" ]
 
    then
 
    echo "mailx is not installed!"
 
echo "Try running the script with --INSTALL"
 
exit 1
 
    fi
 
 
    RSYNC_BIN=`whereis rsync | awk '{print $2}'`
 
    if [ ! -f "$RSYNC_BIN" ]
 
    then
 
    echo $SYNC_BIN
 
echo "Please install "rsync"!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    SSH_BIN=`whereis ssh | awk '{print $2}'`
 
    if [ ! -e "$SSH_BIN" ]
 
    then
 
  echo "Please install "ssh"!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    MD5SUM_BIN=`whereis md5sum | awk '{print $2}'`
 
    if [ ! -e "$MD5SUM_BIN" ]
 
    then
 
  echo "Please install "md5sum"!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
   
 
    if [ ! -d $ZM_HOME ]
 
    then
 
  echo "$ZM_HOME not found!"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    if [ ! -d $SYNC_DIR ]
 
    then
 
    echo "$SYNC_DIR not found!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    if [ ! -d $ARCHIVEDIR ]
 
    then
 
    echo "$ARCHIVEDIR not found!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    if [ ! -d $TOO_MEDIA_DIR ]
 
    then
 
    echo "directory $TOO_MEDIA_DIR not found!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
echo
 
exit 1
 
    fi
 
   
 
    # Look for old backups and put then in directory from where you write them to some form of
 
    # storage media
 
    LAST_FULL_DAR=`ls -A -1 $ARCHIVEDIR | grep $BACKUPNAME | cut -d _ -f1 | head -n1`
 
 
    if [ -z "$LAST_FULL_DAR" ]
 
    then
 
        echo "No old backups found"
 
 
    elif [ "$LAST_FULL_DAR" -lt "$BACKUPWEEK" ]
 
    then
 
        echo "Old backups found...old week= $LAST_FULL_DAR current week= $BACKUPWEEK"
 
        echo
 
        for i in `ls -A -1 "$ARCHIVEDIR""$LAST_FULL_DAR"_"$BACKUPNAME"*`
 
    #for i in `ls -A -1 "$ARCHIVEDIR""$LAST_FULL_DAR"_"$BACKUPNAME"*dar`
 
            do
 
                mv $i $TOO_MEDIA_DIR
 
                if [ "$?" -ne "0" ]
 
                then
 
                    echo "error during move!"
 
                    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
                    exit 1
 
                else
 
                    echo "$i moved to $TOO_MEDIA_DIR"
 
                fi
 
            done
 
    fi
 
     
 
    # Checking for a backup file collisions. Creating Date and Marker file.
 
    CURRENTNAME1=`ls -A -1 "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F"*dar 2> /dev/null | head -qn1`
 
    if [ -f "$CURRENTNAME1" ]
 
    then
 
        echo
 
        echo "Full Zimbra Backup failed!"
 
        echo "FOUND A BACKUP WITH SAME NAME IN $ARCHIVEDIR >> Please check why ????"
 
        echo "!! You should only run this script once a day with the current backup date settings !!"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    else
 
        su -l "$ZM_USER" -c $ZM_HOME"bin/zmcontrol -v" > /dev/null
 
if [ -z "$?" ]
 
        then
 
            echo
 
            echo "zmcontrol has some problems! check config or call for help..."
 
            cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
            exit 1
 
else
 
    echo
 
    echo "Setting date & version Marker into "$ZM_HOME"DATE_VERSION.txt"
 
    echo
 
    echo "$BACKUPDATE" > "$ZM_HOME"DATE_VERSION.txt
 
    su -l "$ZM_USER" -c $ZM_HOME"bin/zmcontrol -v" | grep ^R >> "$ZM_HOME"DATE_VERSION.txt
 
fi
 
 
# HotSync to backup directory
 
echo "Doing a hotsync of $ZM_HOME to $SYNC_DIR"
 
   
 
nice -19 $RSYNC_BIN $RSYNC_OPTS $ZM_HOME $SYNC_DIR
 
if [ "$?" -ne "0" ]
 
then
 
    echo
 
    echo "rsync had threw an hotsync error this is not that wild... continuing"
 
    #cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
else
 
        echo "sync went ok"
 
        echo
 
        fi
 
       
 
   
 
# Stopping Zimbra
 
echo "Stopping the Zimbra server"
 
echo
 
 
#Disable zimbra user's crontab, we don't want it starting any jobs while we backup
 
crontab -u $ZM_USER -l > "$ZM_HOME"crontab.org
 
if [ "$?" -ne "0" ]
 
then
 
    echo "could not backup "$ZM_USER"'s crontab..."
 
    echo "continuing with out changing users crontab!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
else
 
    touch "$ZM_HOME"crontab.blank
 
    crontab -u $ZM_USER "$ZM_HOME"crontab.blank
 
    rm "$ZM_HOME"crontab.blank
 
        echo "Deactivated "$ZM_USER"'s cronjobs"
 
    echo
 
    fi
 
 
#Starting 'service downtime' counter
 
DOWNTIMEA=(`date +%s`)
 
 
su -l $ZM_USER -c $ZM_HOME"bin/zmcontrol stop"
 
if [ "$?" -eq "1" ]
 
then
 
    echo "zmcontrol shutdown had an error!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
else
 
            echo
 
    echo "Zimbra server has stopped "
 
fi
 
        echo
 
        # Some times I still have zimbra procs running, so I murder them! :-O
 
        sleep 5
 
        echo "kill any left over $ZM_USER procs"
 
        PROX=(`ps -u $ZM_USER | awk '{print $1}' | grep -v PID`)
 
        if [ "$PROX" ]
 
        then
 
            ps -u $ZM_USER | awk '{print $1}' | grep -v PID | xargs kill -s 15
 
            echo "Did a Mr. Bush on some left over procs..."
 
            echo 
 
        else
 
            echo "Nothing to kill"
 
            echo
 
        fi
 
        # ColdSyncing the zimbra server
 
        echo "Doing a fast cold sync..."
 
       
 
$RSYNC_BIN $RSYNC_OPTS $ZM_HOME $SYNC_DIR
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo "rsync had threw an error!"
 
    echo "This should not happen at this stage... exiting!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
        else
 
            echo "sync went ok"
 
        fi
 
        echo
 
 
        # Starting the Zimbra server again
 
       
 
#Reinstate zimbra user's crontab
 
crontab -u $ZM_USER "$ZM_HOME"crontab.org
 
if [ "$?" -ne "0" ]
 
then
 
    echo "!!Could not reinstate "$ZM_USER"'s crontab!!"
 
    echo "Please do this manually!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
else
 
    echo "Reinstated "$ZM_USER"'s cronjobs"
 
    echo
 
        fi
 
 
su -l "$ZM_USER" -c $ZM_HOME"bin/zmcontrol start"
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo "There was an error starting Zimbra!"
 
            cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
            exit 1
 
        else
 
            echo
 
            echo "Zimbra has started"
 
        fi
 
# Service Timerc
 
DOWNTIMEB=(`date +%s`)
 
RUNTIME=$(expr $DOWNTIMEB \- $DOWNTIMEA)
 
hours=$(($RUNTIME / 3600))
 
seconds=$(($RUNTIME  % 3600))
 
minutes=$(($RUNTIME  / 60))
 
seconds=$(($RUNTIME  % 60))
 
echo
 
echo "Service down time was - Hr:$hours Min:$minutes Sec:$seconds"
 
        echo
 
       
 
        # Hack to start the stats component
 
        if [ $STATHACK = "yes" ]
 
    then
 
        echo "Running A hack... This one to check and start Stats subsystem"
 
#Checking if Stats is running
 
sleep 5
 
STAT_CK=(`su -l "$ZM_USER" -c $ZM_HOME"bin/zmcontrol status" |grep -i stats | awk '{print $2}'`)
 
if [ "$STAT_CK" = "Stopped" ]
 
        then
 
                    echo "Stats is not running, thus booting Stats subsystem!"
 
                    echo
 
                    # Stopping Stats
 
    su -l $ZM_USER -c $ZM_HOME"bin/zmstatctl stop"
 
                    if [ "$?" -ne "0" ]
 
                    then
 
                        echo "Stopping stats failed!"
 
                        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
                        exit 1
 
                    else
 
        echo "Stats have been stopped"
 
                        echo
 
                    fi
 
 
    # Running Stats cronjob zmlogprocess manually
 
                    su -l $ZM_USER -c $ZM_HOME"libexec/zmlogprocess" > /tmp/logprocess.out 2>&1
 
                    if [ "$?" -ne "0" ]
 
                    then
 
                        echo "Error running 'logprocess'"
 
                        echo
 
                        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
                        exit 1
 
                    else
 
                        echo "Logprocess done..."
 
                        echo
 
                    fi
 
               
 
    # Running Stats cronjob zmqueuelog manually               
 
    su -l $ZM_USER -c $ZM_HOME"libexec/zmqueuelog"
 
                    if [ "$?" -ne "0" ]
 
                    then
 
                        echo "Error running 'libexec/zmqueuelog'"
 
                        echo
 
                        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
                        exit 1
 
                    else
 
                        echo "zmqueuelog done..."
 
                        echo
 
                    fi
 
   
 
    # Starting Stats
 
    sleep 2
 
    su -l "$ZM_USER" -c $ZM_HOME"bin/zmstatctl start"
 
            if [ "$?" -ne "0" ]
 
    then
 
        echo "Starting stats failed!"
 
                        echo
 
        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
        exit 1
 
    else
 
        echo "Stats started..."
 
    fi
 
            else
 
echo "Hack not needed Stats seems to be running fine..."
 
            fi
 
fi
 
         
 
        # Status Check to see that is running
 
STATUS=(`su -l "$ZM_USER" -c "/opt/zimbra/bin/zmcontrol status" | grep -i Stopped`)
 
        if [ "$STATUS" ]
 
        then
 
            echo
 
            echo "Services that are not running"
 
            echo $STATUS
 
            cat $LOG | mail -c $EMAILCC -s "Zimbra Services Stopped on `hostname --fqdn`" $EMAIL
 
        else
 
            echo
 
            echo "All services are running"
 
            echo
 
        fi
 
        echo
 
        echo "Writing a full backup called:"
 
echo " $BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F"
 
        echo "in: $ARCHIVEDIR with file sizes of max: $ARCHIVESIZE"
 
cd $SYNC_DIR
 
if [ $CRYPT = "yes" ]
 
then
 
    KEY=`cat "$PASSDIR""$PASSFILE"`
 
    echo "Archive is Encrypted"
 
    nice -19 $DAR_BIN -K bf:$KEY -s $ARCHIVESIZE -z$COMPRESS -Z "*.gz" -Z "*.zip"\
 
    -Z "*.bz2" -Z "*.tgz" -Z "*.zgz" -Z "*.jar" -Z "*.tiff" \
 
                    -Z "*.jpg" -Z "*.png" -Z "*.gif" -Z "*.jpeg" -R `pwd` \
 
                    -c "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F" -Q
 
else       
 
    echo "Archive is NOT Encrypted!!!"
 
    nice -19 $DAR_BIN -s $ARCHIVESIZE -z$COMPRESS -Z "*.gz" -Z "*.zip"\
 
    -Z "*.bz2" -Z "*.tgz" -Z "*.zgz" -Z "*.jar" -Z "*.tiff" \
 
    -Z "*.jpg" -Z "*.png" -Z "*.gif" -Z "*.jpeg" -R `pwd` \
 
    -c "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F" -Q
 
fi
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo
 
            echo "Dar had a problem!"
 
            cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
            exit 1
 
        else
 
            echo "Archive Created successfully"
 
            echo
 
    # Create MD5 Checksums to verify archives after writing to media or network transfers
 
    cd $ARCHIVEDIR
 
    FILENAME=`ls -A "$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F"*`
 
    if [ -e $FILENAME ]
 
    then
 
    echo "Create MD5 Checksum for $FILENAME"
 
    $MD5SUM_BIN -b $FILENAME > "$FILENAME".md5
 
    if [ "$?" -ne "0" ]
 
    then
 
        echo
 
        echo "MD5 Checksum failed!"
 
        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
        exit 1
 
    else
 
        echo
 
        echo "MD5 Checksum Created successfully"
 
                echo
 
    fi
 
    else
 
    echo "$FILENAME not found!"
 
echo "This should not happen"
 
echo
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
fi
 
# DRCP Section. To scp newly created archives to a remote system
 
if [ $DRCP = "yes" ]
 
then
 
    CPNAME=`ls -A "$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F"*`
 
    echo "copy archive to $REMOTEHOST" remote directory $REMOTEDIR
 
    scp -i /root/.ssh/id_rsa $CPNAME "$SSHUSER"@"$REMOTEHOST":"$REMOTEDIR"
 
if [ "$?" -ne "0" ]
 
then
 
            echo
 
    echo "Error copying archive and checksum to $REMOTEHOST"
 
                echo
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
        fi
 
fi
 
    fi
 
   
 
    # over view of all the files which where backed up
 
    echo
 
    echo "Create file listing from archive"
 
    if [ $CRYPT = "yes" ]
 
then
 
    KEY=`cat "$PASSDIR""$PASSFILE"`
 
    nice -19 $DAR_BIN -K bf:$KEY -l "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F" -Q\
 
    > "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt && gzip -9 "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt
 
else       
 
    nice -19 $DAR_BIN -l "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_F" -Q\
 
    > "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt && gzip -9 "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt
 
fi
 
    # Script Timer
 
    STOPTIME=(`date +%s`)
 
    RUNTIME=$(expr $STOPTIME \- $STARTTIME)
 
    hours=$(($RUNTIME / 3600))
 
    seconds=$(($RUNTIME  % 3600))
 
    minutes=$(($RUNTIME  / 60))
 
    seconds=$(($RUNTIME  % 60))
 
    echo
 
    echo "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
 
    echo "Full Zimbra Backup ended at: `date +%H:%M`"
 
    echo "Backup took Hr:$hours Min:$minutes Sec:$seconds to complete"
 
    echo ":::::::::::::::::Cheers Osoffice for the script:::::::::::::::::::::::"
 
    (cat $LOG; $UUENCODE "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt.gz "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt.gz) | mail -c $EMAILCC \
 
    -s "Zimbra Full Backup Log on `hostname --fqdn`" $EMAIL
 
    echo
 
    ;;
 
 
    -d | --diff)
 
    echo
 
    echo "      Diff Backup started at: `date +%H:%M`"
 
 
   
 
    DAR_BIN=`whereis dar | awk '{print $2}'`
 
    if [ ! -e "$DAR_BIN" ]
 
    then
 
    echo "Please install "dar"!"
 
echo "Try running the script with --INSTALL"
 
exit 1
 
    fi
 
 
    MAILX=`whereis mailx | awk '{print $2}'`
 
    if [ ! -e "$MAILX" ]
 
    then
 
    echo "mailx is not installed!"
 
echo "Try running the script with --INSTALL"
 
exit 1
 
    fi
 
 
    RSYNC_BIN=`whereis rsync | awk '{print $2}'`
 
    if [ ! -f "$RSYNC_BIN" ]
 
    then
 
    echo $SYNC_BIN
 
echo "Please install "rsync"!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    SSH_BIN=`whereis ssh | awk '{print $2}'`
 
    if [ ! -e "$SSH_BIN" ]
 
    then
 
  echo "Please install "ssh"!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    MD5SUM_BIN=`whereis md5sum | awk '{print $2}'`
 
    if [ ! -e "$MD5SUM_BIN" ]
 
    then
 
  echo "Please install "md5sum"!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
   
 
    if [ ! -d $ZM_HOME ]
 
    then
 
  echo "$ZM_HOME not found!"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    if [ ! -d $SYNC_DIR ]
 
    then
 
    echo "$SYNC_DIR not found!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    if [ ! -d $ARCHIVEDIR ]
 
    then
 
    echo "$ARCHIVEDIR not found!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
 
    if [ ! -d $TOO_MEDIA_DIR ]
 
    then
 
    echo "directory $TOO_MEDIA_DIR not found!"
 
echo "Try running the script with --INSTALL"
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
echo
 
exit 1
 
    fi
 
       
 
    CURRENTNAME2=`ls -A -1 "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D"*dar 2> /dev/null | head -qn1`
 
    CURRENTFULL=`ls -A -1 "$ARCHIVEDIR""$BACKUPWEEK"*FULL*dar 2>/dev/null | cut -d . -f1 `
 
 
    if [ -f "$CURRENTNAME2" ]
 
    then
 
        echo "Full Zimbra Backup failed! FOUND A BACKUP WITH SAME NAME"
 
        echo "Please check why! You should only run this script once a day with the current backup date settings!"
 
        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
        exit 1
 
    elif [ $CURRENTFULL ]
 
    then
 
        echo
 
        # HotSync to backup directory
 
        echo "Doing a hotsync of $ZM_HOME to $SYNC_DIR"
 
nice -19 $RSYNC_BIN $RSYNC_OPTS $ZM_HOME $SYNC_DIR
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo
 
    echo "rsync had threw an hotsync error this is not that wild... continuing"
 
            #cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
else
 
            echo
 
    echo "sync went ok"
 
    fi
 
         
 
    echo
 
 
    # Stopping Zimbra
 
    echo "Stopping the Zimbra server"
 
    echo
 
 
#Disable zimbra user's crontab, we don't want it starting any jobs while we backup
 
crontab -u $ZM_USER -l > "$ZM_HOME"crontab.org
 
if [ "$?" -ne "0" ]
 
then
 
    echo "could not backup "$ZM_USER"'s crontab..."
 
    echo "continuing with out changing users crontab!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
else
 
    touch "$ZM_HOME"crontab.blank
 
    crontab -u $ZM_USER "$ZM_HOME"crontab.blank
 
    rm "$ZM_HOME"crontab.blank
 
        echo "Deactivated "$ZM_USER"'s cronjobs"
 
    echo
 
    fi
 
 
#Starting 'service downtime' counter
 
DOWNTIMEA=(`date +%s`)
 
 
su -l $ZM_USER -c $ZM_HOME"bin/zmcontrol stop"
 
if [ "$?" -eq "1" ]
 
then
 
    echo "zmcontrol shutdown had an error!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
else
 
            echo
 
    echo "Zimbra server has stopped "
 
fi
 
        echo
 
        # Some times I still have zimbra procs running, so I murder them! :-O
 
        sleep 5
 
        echo "kill any left over $ZM_USER procs"
 
        PROX=(`ps -u $ZM_USER | awk '{print $1}' | grep -v PID`)
 
        if [ "$PROX" ]
 
        then
 
            ps -u $ZM_USER | awk '{print $1}' | grep -v PID | xargs kill -s 15
 
            echo "Did a Mr. Bush on some left over procs..."
 
            echo 
 
        else
 
            echo "Nothing to kill"
 
            echo
 
        fi
 
        # ColdSyncing the zimbra server
 
        echo "Doing a fast cold sync..."
 
       
 
$RSYNC_BIN $RSYNC_OPTS $ZM_HOME $SYNC_DIR
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo "rsync had threw an error!"
 
    echo "This should not happen at this stage... exiting!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
        else
 
            echo "sync went ok"
 
        fi
 
        echo
 
 
        # Starting the Zimbra server again
 
       
 
#Reinstate zimbra user's crontab
 
crontab -u $ZM_USER "$ZM_HOME"crontab.org
 
if [ "$?" -ne "0" ]
 
then
 
    echo "!!Could not reinstate "$ZM_USER"'s crontab!!"
 
    echo "Please do this manually!"
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
else
 
    echo "Reinstated "$ZM_USER"'s cronjobs"
 
    echo
 
        fi
 
 
su -l "$ZM_USER" -c $ZM_HOME"bin/zmcontrol start"
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo "There was an error starting Zimbra!"
 
            cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
            exit 1
 
        else
 
            echo
 
            echo "Zimbra has started"
 
        fi
 
# Service Timerc
 
DOWNTIMEB=(`date +%s`)
 
RUNTIME=$(expr $DOWNTIMEB \- $DOWNTIMEA)
 
hours=$(($RUNTIME / 3600))
 
seconds=$(($RUNTIME  % 3600))
 
minutes=$(($RUNTIME  / 60))
 
seconds=$(($RUNTIME  % 60))
 
echo
 
echo "Service down time was - Hr:$hours Min:$minutes Sec:$seconds"
 
        echo
 
       
 
        # Hack to start the stats component
 
        if [ $STATHACK = "yes" ]
 
    then
 
        echo "Running A hack... This one to check and start Stats subsystem"
 
#Checking if Stats is running
 
sleep 5
 
STAT_CK=(`su -l "$ZM_USER" -c $ZM_HOME"bin/zmcontrol status" |grep -i stats | awk '{print $2}'`)
 
if [ "$STAT_CK" = "Stopped" ]
 
        then
 
                    echo "Stats is not running, thus booting Stats subsystem!"
 
                    echo
 
                    # Stopping Stats
 
    su -l $ZM_USER -c $ZM_HOME"bin/zmstatctl stop"
 
                    if [ "$?" -ne "0" ]
 
                    then
 
                        echo "Stopping stats failed!"
 
                        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
                        exit 1
 
                    else
 
        echo "Stats have been stopped"
 
                        echo
 
                    fi
 
 
    # Running Stats cronjob zmlogprocess manually
 
                    su -l $ZM_USER -c $ZM_HOME"libexec/zmlogprocess" > /tmp/logprocess.out 2>&1
 
                    if [ "$?" -ne "0" ]
 
                    then
 
                        echo "Error running 'logprocess'"
 
                        echo
 
                        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
                        exit 1
 
                    else
 
                        echo "Logprocess done..."
 
                        echo
 
                    fi
 
               
 
    # Running Stats cronjob zmqueuelog manually               
 
    su -l $ZM_USER -c $ZM_HOME"libexec/zmqueuelog"
 
                    if [ "$?" -ne "0" ]
 
                    then
 
                        echo "Error running 'libexec/zmqueuelog'"
 
                        echo
 
                        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
                        exit 1
 
                    else
 
                        echo "zmqueuelog done..."
 
                        echo
 
                    fi
 
   
 
    # Starting Stats
 
    sleep 2
 
    su -l "$ZM_USER" -c $ZM_HOME"bin/zmstatctl start"
 
            if [ "$?" -ne "0" ]
 
    then
 
        echo "Starting stats failed!"
 
                        echo
 
        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
        exit 1
 
    else
 
        echo "Stats started..."
 
    fi
 
            else
 
echo "Hack not needed Stats seems to be running fine..."
 
            fi
 
fi
 
         
 
        # Status Check to see that is running
 
STATUS=(`su -l "$ZM_USER" -c "/opt/zimbra/bin/zmcontrol status" | grep -i Stopped`)
 
        if [ "$STATUS" ]
 
        then
 
            echo
 
            echo "Services that are not running"
 
            echo $STATUS
 
            cat $LOG | mail -c $EMAILCC -s "Zimbra Services Stopped on `hostname --fqdn`" $EMAIL
 
        else
 
            echo
 
            echo "All services are running"
 
            echo
 
    fi
 
    echo
 
   
 
    echo "Writing a diff backup called:"
 
    echo " $BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D"
 
    echo "in: $ARCHIVEDIR with file sizes of max: $ARCHIVESIZE"
 
    cd $SYNC_DIR
 
if [ $CRYPT = "yes" ]
 
then
 
    KEY=`cat "$PASSDIR""$PASSFILE"`
 
    echo "Archive is Encrypted"
 
    nice -19 $DAR_BIN -J bf:$KEY -s $ARCHIVESIZE -z$COMPRESS -Z "*.gz" -Z "*.zip"\
 
    -Z "*.bz2" -Z "*.tgz" -Z "*.zgz" -Z "*.jar" -Z "*.tiff" \
 
                    -Z "*.jpg" -Z "*.png" -Z "*.gif" -Z "*.jpeg" -R `pwd` \
 
                    -c "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D" -Q\
 
                    -A "$CURRENTFULL" -Q
 
else       
 
    echo "Archive is NOT Encrypted!!!"
 
    nice -19 $DAR_BIN -s $ARCHIVESIZE -z$COMPRESS -Z "*.gz" -Z "*.zip"\
 
    -Z "*.bz2" -Z "*.tgz" -Z "*.zgz" -Z "*.jar" -Z "*.tiff" \
 
    -Z "*.jpg" -Z "*.png" -Z "*.gif" -Z "*.jpeg" -R `pwd` \
 
    -c "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D" -Q\
 
    -A "$CURRENTFULL" -Q
 
fi
 
        if [ "$?" -ne "0" ]
 
        then
 
            echo
 
            echo "Dar had a problem!"
 
            cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
            exit 1
 
        else
 
            echo "Archive Created successfully"
 
            echo
 
    # Create MD5 Checksums to verify archives after writing to media or network transfers
 
    cd $ARCHIVEDIR
 
    FILENAME=`ls -A "$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D"*`
 
    if [ -e $FILENAME ]
 
    then
 
    echo "Create MD5 Checksum for $FILENAME"
 
    $MD5SUM_BIN -b $FILENAME > "$FILENAME".md5
 
    if [ "$?" -ne "0" ]
 
    then
 
        echo
 
        echo "MD5 Checksum failed!"
 
        cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
        exit 1
 
    else
 
        echo
 
        echo "MD5 Checksum Created successfully"
 
                echo
 
    fi
 
    else
 
    echo "$FILENAME not found!"
 
echo "This should not happen"
 
echo
 
cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
exit 1
 
    fi
 
fi
 
# DRCP Section. To scp newly created archives to a remote system
 
if [ $DRCP = "yes" ]
 
then
 
    CPNAME=`ls -A "$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D"*`
 
    echo "copy archive to $REMOTEHOST" remote directory $REMOTEDIR
 
    scp -i /root/.ssh/id_rsa $CPNAME "$SSHUSER"@"$REMOTEHOST":"$REMOTEDIR"
 
if [ "$?" -ne "0" ]
 
then
 
            echo
 
    echo "Error copying archive and checksum to $REMOTEHOST"
 
                echo
 
    cat $LOG | mail -c $EMAILCC -s "Zimbra backup error on `hostname --fqdn`" $EMAIL
 
    exit 1
 
        fi
 
fi
 
    fi
 
   
 
    # over view of all the files which where backed up
 
    echo
 
    echo "Create file listing from archive"
 
    if [ $CRYPT = "yes" ]
 
then
 
    KEY=`cat "$PASSDIR""$PASSFILE"`
 
    nice -19 $DAR_BIN -K bf:$KEY -l "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D" -Q\
 
    > "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt && gzip -9 "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt
 
else       
 
    nice -19 $DAR_BIN -l "$ARCHIVEDIR""$BACKUPWEEK"_"$BACKUPNAME"_"$BACKUPDATE"_"$BACKUPTYPE_D" -Q\
 
    > "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt && gzip -9 "$ARCHIVEDIR"Backuplist-"$BACKUPDATE".txt
 
    fi
 
    # Script Timer
 
    STOPTIME=(`date +%s`)
 
    RUNTIME=$(expr $STOPTIME \- $STARTTIME)
 
    hours=$(($RUNTIME / 3600))
 
    seconds=$(($RUNTIME  % 3600))
 
    minutes=$(($RUNTIME  / 60))
 
    seconds=$(($RUNTIME  % 60))
 
    echo
 
    echo "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
 
    echo "Diff Zimbra Backup ended at: `date +%H:%M`"
 
    echo "Backup took Hr:$hours Min:$minutes Sec:$seconds to complete"
 
    echo ":::::::::::::::::::Cheers Osoffice the script:::::::::::::::::::::::::"
 
    echo
 
    ;;
 
 
    *)
 
    echo
 
    echo "use -h or --help for assistance"
 
    echo
 
    ;;
 
  
    esac
 
exit 0
 
 
</pre>
 
</pre>
  
Line 1,977: Line 944:
 
It may be possible to create a cron job to do these tasks automatically.
 
It may be possible to create a cron job to do these tasks automatically.
  
Copy Command: cp -rp /opt/zimbra [location path]
+
Copy Command: cp -Rp /opt/zimbra [location path]
  
 
Depending on your hardware and the amount of data contained in your Zimbra installation, this process can take a while.
 
Depending on your hardware and the amount of data contained in your Zimbra installation, this process can take a while.
Line 1,990: Line 957:
 
You may be able to scavenge data, if needed. If you simply do not want the old data, you can skip this part.
 
You may be able to scavenge data, if needed. If you simply do not want the old data, you can skip this part.
  
  >[insert command for renaming here]
+
  >mv /opt/zimbra [new location i.e. /tmp/zimbra-old]
  
 
''You may want to move it completly out of the /opt folder just to be safe.''
 
''You may want to move it completly out of the /opt folder just to be safe.''
Line 1,998: Line 965:
 
  >cp -rp [location of backup] /opt
 
  >cp -rp [location of backup] /opt
  
  >[insert command for renaming here]
+
  >mv /opt/[backup name] /opt/zimbra
  
 
====Restore to Existing/Backup Zimbra Server====
 
====Restore to Existing/Backup Zimbra Server====
Line 2,062: Line 1,029:
  
 
again after that.  It appears that zmfixperms is supposed to chown zimbra:zimbra on something, but it misses it.  This way, you chown EVERYTHING zimbra:zimbra, and zmfixperms puts back things that need to be owned as root, postfix, etc.
 
again after that.  It appears that zmfixperms is supposed to chown zimbra:zimbra on something, but it misses it.  This way, you chown EVERYTHING zimbra:zimbra, and zmfixperms puts back things that need to be owned as root, postfix, etc.
 +
 +
====Disaster Recovery====
 +
 +
In the unfortunate event of losing your complete server or installation, the following will get you up and running.
 +
 +
'''This has been tested successfully on v5.0.5'''
 +
 +
* The machine you are recovering to '''must''' have the same hostname as the original machine.
 +
 +
* Once you have your OS and all pre-requisites installed. Download and install Zimbra as normal, using the same zimbra version as the backup. If it is a new server, you can install using install.sh -s to install just the packages to create the users and programs before recreating the old installation/
 +
 +
* Once Zimbra is installed, stop all Zimbra services and move/rename the /opt/zimbra folder:
 +
sudo -u zimbra /opt/zimbra/bin/zmcontrol shutdown
 +
mv /opt/zimbra /tmp/zimbra-old
 +
 +
* Uncompress the most recent backup file to the /opt/zimbra folder
 +
mkdir /opt/zimbra
 +
tar zxvf [backup file] -C /opt/zimbra
 +
 +
or if you prefer...
 +
 +
tar zxvf [backup file] -C /tmp/zimbra-backup
 +
cp -Rp /tmp/zimbra-backup /opt/zimbra
 +
 +
* Fix the Zimbra permissions
 +
chown -R zimbra:zimbra /opt/zimbra
 +
/opt/zimbra/libexec/zmfixperms
 +
 +
* Restart all Zimbra services
 +
sudo -u zimbra /opt/zimbra/bin/zmcontrol startup
 +
zmcontrol startup
 +
 +
You should now be able to access Zimbra as normal. If not, you may need to "upgrade" zimbra to set up the old configuration, for example if you have zimbra listening on a web port other than 80.
 +
install.sh from the directory you extracted the zimbra install to. This will also restart services when completed, so you should be up and running
 +
 +
{{Article Footer|ZCS 4.0, 4.5.7 and 5.0.5|5/16/2006}}
 +
 +
[[Category:Backup and Restore]]
 +
[[Category:Disaster Recovery]]
 +
[[Category:ZCS 5.0]]
 +
[[Category:ZCS 4.5]]

Latest revision as of 03:10, 11 July 2015

Open Source Edition Backup Procedure

   KB 1534        Last updated on 2015-07-11  




0.00
(0 votes)

If you wish to have a more automated backup feature, you should try the Network Version of Zimbra.

Backup Scripts

Backup Using LVM

If you have your Zimbra installation on its own logical volume, you can use this script:

#!/bin/bash
  
time=`date +%Y-%m-%d_%H-%M-%S`

# Modify the following variables according to your installation
#########################################

# backup_dir - directory to backup to
backup_dir=/path/to/backups/$time

# vol_group - the Volume Group that contains $zimbra_vol
vol_group=PUT_VOL_GROUPNAME_HERE

# zimbra_vol - the Logical Volume that contains /opt/zimbra
zimbra_vol=PUT_ZIMBRA_VOLNAME_HERE

# zimbra_vol_fs - the file system type (ext3, xfs, ...) in /opt/zimbra
zimbra_vol_fs=PUT_ZIMBRA_FILE_SYSTEM_TYPE_HERE

# lvcreate and lvremove commands path - 
lvcreate_cmd=`which lvcreate`
lvremove_cmd=`which lvremove`
  
# Do not change anything beyond this point
#########################################

# Test for an interactive shell
if [[ $- != *i* ]]
   then say() { echo -e $1; }
     # Colors, yo!
     GREEN="\e[1;32m"
     RED="\e[1;31m"
     CYAN="\e[1;36m"
     PURPLE="\e[1;35m"
   else say() { true; } # Do nothing
fi

# Output date
say $GREEN"Backup started at "$RED"`date`"$GREEN"."

# Stop the Zimbra services
say $CYAN"Stopping the Zimbra services..."
say $PURPLE"  This may take several minutes."
/etc/init.d/zimbra stop

# Create a logical volume called ZimbraBackup
say $GREEN"Creating a LV called ZimbraBackup:"$PURPLE
$lvcreate_cmd -L1000M -s -n ZimbraBackup /dev/$vol_group/$zimbra_vol

# Create a mountpoint to mount the logical volume to
say $GREEN"Creating a mountpoint for the LV..."
# WARNING: this is insecure!
mkdir -p /tmp/ZimbraBackup

# Mount the logical volume to the mountpoint
say $GREEN"Mounting the LV..."
# WARNING: remove nouuid option if the filesystem is not formatted as XFS !!!   
mount -t $zimbra_vol_fs -o nouuid,ro /dev/$vol_group/ZimbraBackup /tmp/ZimbraBackup/

# Start the Zimbra services
say $CYAN"Starting the Zimbra services..."
# WARNING: it's safer not to put this command in background
/etc/init.d/zimbra start &

# For testing only
#say $RED"Press Enter to continue...\e[0m"
#read input

# Create the current backup
say $GREEN"Creating the backup directory and backup..."
mkdir -p $backup_dir
tar zcvf $backup_dir/zimbra.backup.tar.gz /tmp/ZimbraBackup/zimbra/ 2&> /dev/null

# Unmount /tmp/ZimbraBackup and remove the logical volume
say $GREEN"Unmounting and removing the LV."$PURPLE
umount /tmp/ZimbraBackup/
$lvremove_cmd --force /dev/$vol_group/ZimbraBackup

# Done!
say $GREEN"Zimbra backed up to "$CYAN$backup_dir$GREEN"!"
say $GREEN"Backup ended at "$RED"`date`"$GREEN".\e[0m"

More elaborated script, using LVM and rsync

More info at https://github.com/sergevanginderachter/sysadmintools/tree/master/zimbrackup

Yet another backup script, using LVM and duplicity

The previous examples use tar and rsync respectively. Both have disadvantages:

  • they don't support incremental backups
  • you need to do additional scripting to encrypt the backup and purging of old backups

I modified the first script to use duplicity instead of plain tar. This way you have the flexibility to use any protocol you like (scp, rsync, ftp) to upload the backup, you don't have to worry about old backups and you can save a lot of disk space!

Get the script: http://www.nervous.it/2007/01/zimbra-lvm-backup-with-duplicity-volume/ Get duplicity: http://duplicity.nongnu.org/

The Perl way of doing it (without LVM)

ZCS Tools currently contains a Cold Backup script written in Perl. It also supports backup rotation. This script does not use LVM.

Currently: zimbraColdBackup-Ver0.02beta

#!/usr/bin/perl
use strict;
use warnings;
use POSIX;
use IO::Scalar; # for building up output on a string
use Proc::ProcessTable; # for killing processes
use File::Path; # for removing directories
use File::Rsync; # for syncing using rsync
use Mail::Mailer; # for sending email

#############################################################################
# Please make changes below to suit your system and requirements

# absolute path to'rsync' on your system
my $rsync       = '/usr/bin/rsync'; 

# absolute path to zimbra directory
my $zimbra      = '/opt/zimbra';

# absolute path to backup directory. ensure that it exists!
my $backup_dir  = '/backup';

# do you want to rotate backups?
my $rotate_bak  = 1; # 1 = yes, 0 = no

# if yes, after how many days?
# make sure that you don't specify '0'. Specifying zero will delete even
# the latest backup - that is, the backup taken today and you will end up
# with no data!
my $rotate_days = 7;

# do you want to send the backups to a remote location? (using rsync)
my $send_remote = 0; # 1 = yes, 0 = no

# if you would like to use Rsync to send to remote location:
# please enter the destination server below
# (before using the script make sure that you have password-less and
# passphrase-less SSH login setup using private / public cryptography
# this script will neither provide SSH password nor the passphrase
my $ssh_server  = 'host.domain.com'; # SSH server IP or hostname
my $remote_path = '/backups'; # path on remote server to send backup

# Finally:
# Do you want to have the results of backup emailed?
my $send_result = 1; # 1 = yes, 0 = no

# if yes, to whom whould it be emailed?
my $to_email    = 'smile@sis.net.in';

# CC email (optional: you can leave this empty)
my $cc_email    = '';

# BCC email (optional: you can leave this empty)
my $bcc_email   = '';

# Sender / From email (it will look like the email arrive from this person)
my $from_email  = 'root@localhost';

# That's it!
# Don't edit below this line unless you know what you're doing
#############################################################################

my $zimbra_user = 'zimbra';
my $prog_name = $0;

# properties of this program

# name of program
my $progname    = "zimbraColdBackup";
# version number
my $version     = "0.2Beta";
# revision number (independent of version number)
my $revision    = "30";
# license under which distributed
my $license     = qq(
#############################################################################
# Program Name      $progname                                        #
# Program Version   $version                                                 #
# Program Revision  $revision                                                      #
#                                                                           #
# This script can be used to backup Zimbra Collaboration Suite 4.0.0 GA     #
#                                                                           #
# Most recent version of this script can be downloaded from:                #
# http://sourceforge.net/projects/zcstools/                                 #
#                                                                           #
# Copyright (C) 2006 Chintan Zaveri                                         #
# E-mail: smile\@sis.net.in                                                  #
#                                                                           #
# This program is free software; you can redistribute it and/or modify      #
# it under the terms of the GNU General Public License version 2, 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.                              #
#                                                                           #
# 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.               #
#############################################################################
);

# usage text
my $usage = qq(
Usage:
    zimbraColdBackup OPTION

    help|usage|?|--help|--usage
        All of these options, or providing no options will print this text
        about usage.

    overview|--overview
        What this script does.

    install|installation|--install|--installation
        These options will display a text on installation of this script.

    confirm|--confirm
        These options will run the backup procedure.

    version|--version
        These options will print the Name, Version and Revision Number for
        this script.

    license|licence|lisense|lisence|--license|--licence|--lisense|--lisence
        These options will print the License under which this program is
        distributed.
);

# overview text
my $overview = qq(
Overview:

This script can be used to take off-line backup of Zimbra Collaboration Suite.

The following is the series of actions undertaken by this script:

1. Stop Zimbra
2. Backup Zimbra in the specified local directory using Rsync
3. Start Zimbra

Optionally, if you specified, this script will also do the following:

1. Rotate the backups
2. Send the backup to another system using Rsync
3. Email the results of backup
);

# installation text
my $installation = qq(
Installation:

It is fairly easy to install this script. The installation requires you to do
the following:

1. Install all required Perl modules
2. Configure this script
3. Run it once - Test it!
4. Schedule it using crontab

1. Install all required Perl modules

The best way to do this is by running the script. Once you run the script, you
would receive an error message similar to the following:

Can't locate Mail/Mailer.pm in \@INC (\@INC contains:
/usr/lib/perl5/5.8.5/i386-linux-thread-multi /usr/lib/perl5/5.8.5
/usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.4/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.2/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.5 /usr/lib/perl5/site_perl/5.8.4
/usr/lib/perl5/site_perl/5.8.3 /usr/lib/perl5/site_perl/5.8.2
/usr/lib/perl5/site_perl/5.8.1 /usr/lib/perl5/site_perl/5.8.0
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.4/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.2/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.1/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.5 /usr/lib/perl5/vendor_perl/5.8.4
/usr/lib/perl5/vendor_perl/5.8.3 /usr/lib/perl5/vendor_perl/5.8.2
/usr/lib/perl5/vendor_perl/5.8.1 /usr/lib/perl5/vendor_perl/5.8.0
/usr/lib/perl5/vendor_perl .) at ./ZimbraColdBackup.pl line 9.
BEGIN failed--compilation aborted at ./zimbraColdBackup.pl line 9.

In the first line you can see that it is unable to locate Mail/Mailer.pm

To install this module, just type the following:

perl -MCPAN -e 'install Mail::Mailer'

This command will install the Mail::Mailer module.

Remember, the "/" must be converted to "::" when providing the command and
the ".pm" must be removed.

You may receive such errors for a few times. Just install the relevant
modules.

2. Configure the script

Once the modules are installed, you need to open this script in a text editor,
such as "vi" or "nano". Please enter correct values against the variables at
the top of the script. Once you open it in a text editor, it will become
self-explanatory.

3. Run it once - Test it!

Just say: "./zimbraColdBackup confirm" after you have configured it. It should
run and do as promised. If it doesn't just let me know, or ensure that it has
been properly configured.

4. Schedule it using crontab

Create a cron job using the command 'crontab -e' to run the script at fixed
intervals.
);

# parse the arguments

# if there are no arguments print usage and die
die $usage, @_ if ( $#ARGV + 1 < 1 );

# what was the argument? (ignore more than one arguments...)
my $option = $ARGV[0];

# select action
if (    ( $option =~ /^(--)?help$/ )     ||
        ( $option =~ /^(--)?usage$/ )    ||
        ( $option =~ /^\?$/) 
   ) {
        die $usage, @_;
}
elsif   ( $option =~ /^(--)?overview$/ ) {
        die $overview, @_;
}
elsif   ( $option =~ /^(--)?install(ation)?$/ ) {
        die $installation, @_;
}
elsif   ( $option =~ /^(--)?confirm$/ ) {
        1; # go ahead and run the script
}
elsif   ( $option =~ /^(--)?version$/) {
        die $progname, " Ver. ", $version, " Rev. ", $revision, "\n", @_;
}
elsif   ( $option =~ /^(--)?li[sc]en[sc]e$/ ) {
        die $license, @_;
}
else {
        die "Invalid option: Please try again", $usage, @_;
}

# going ahead and running the script :-)

# check inputs

if  ( ( $rsync eq "" ) || ( $rsync !~ /^\// ) ) {
    die "Please provide an absolute path to 'rsync'", "\n", @_;
}

if  (! ( -d $zimbra ) ) {
    die "Please provide an absolute path to 'zimbra' directory", "\n", @_;
}

if  (! ( -d $backup_dir ) ) {
    die "Please provide an absolute path to backup directory", "\n", @_;
}

if  ( $send_remote =~ /\D/ ) {
    die "Please enter either '1' or '0' in \$send_remote", "\n", @_;
}

if  ( $send_remote ) {
    # check ssh params
    if ( $ssh_server eq "" ) {
        die "Please enter valid SSH server to rsync to.", "\n", @_;
    }
}

if  ( $rotate_bak =~ /\D/ ) {
    die "Please enter either '1' or '0' in \$rotate_bak", "\n", @_;
}

if  ( $rotate_days =~ /\D/ ) {
    die "Please enter either '1' or '0' in \$rotate_days", "\n", @_;
}

if  ( $send_result =~ /\D/ ) {
    die "Please enter either '1' or '0' in \$send_result", "\n", @_;
}

if  ( $send_result ) {
    if  ( ! $to_email ) {
        die "Please enter valid email in \$to_email", "\n", @_;
    }
    if  ( ! $from_email ) {
        die "Please enter valid email in \$from_email", "\n", @_;
    }
}

# if you reach here, everything is valid, please proceed

my $result = '';
my $res_fh = IO::Scalar->new ( \$result );
# now whatever output we want to build up, we will print to $res_fh

print $res_fh "Date: ",
    POSIX::strftime ( '%m-%d-%Y, %A, %H:%M', localtime ( time ) ),
    " Hours\n";

# current day, date, month, time, ...
my $current_time = POSIX::strftime ( '%m-%d-%Y-%A-%H-%M', localtime ( time ) );
my $since_epoch = time ( ); # seconds since epoch

my $bak_dir = $backup_dir; # we want to use the backup dir path later
$backup_dir .= '/'.$current_time.'-'.$since_epoch;

# Stop Zimbra
my $zmstopstat = system ( "su - zimbra -c '$zimbra/bin/zmcontrol stop'" );
if ( $zmstopstat ) {
    print $res_fh "Stopping Zimbra: Some Problem Occurred. Please check.\n";
}
else {
    print $res_fh "Stopping Zimbra: Success\n";
}

# Kill all lingering Zimbra processes
my $zimbra_uid = getpwnam ( $zimbra_user );

my $process_table = Proc::ProcessTable->new;

# Gracefully kill lingering processes: kill -15, sleep, kill -9
foreach my $process ( @{$process_table->table} ) {
    if  ( ( $process->uid eq $zimbra_uid )          || 
        ( ( $process->cmndline =~ /$zimbra_user/ )  && 
        ( $process->cmndline !~ /$prog_name/ ) ) ) 
        {
            kill -15, $process->pid; # thanks, merlyn
            sleep 10; # not sure if there'll be buffering.
            kill -9, $process->pid;
    }
}

# Backup Zimbra using "rsync"
my $rsync_obj = File::Rsync->new ( {
    'rsync-path'    => $rsync,
    'archive'       => 1,
    'recursive'     => 1,
    'links'         => 1,
    'hard-links'    => 1,
    'keep-dirlinks' => 1,
    'perms'         => 1,
    'owner'         => 1,
    'group'         => 1,
    'devices'       => 1,
    'times'         => 1
} );

my $zmrsyncstat = $rsync_obj->exec ( { 
    src     =>  "$zimbra/", 
    dest    =>  "$backup_dir" 
} );

if ( $zmrsyncstat ) {
    print $res_fh "Rsync Zimbra: Successfully created $backup_dir\n";
}
else {
    print $res_fh "Rsync Zimbra: Some Problem Occurred. Please check.\n";
}

# Now that backup is done, start Zimbra
my $zmstartstat = system ( "su - zimbra -c '$zimbra/bin/zmcontrol start'" );
if ( $zmstartstat ) {
    print $res_fh "Starting Zimbra: Some Problem Occurred. Please check.\n";
}
else {
    print $res_fh "Starting Zimbra: Success\n";
}

print $res_fh "Zimbra was off-line for: ", time ( ) - $since_epoch, " seconds\n";

# Rotate backups
if ( $rotate_bak ) { # should we rotate backups?
    # get a list of all files from the backup directory
    opendir ( DIR, $bak_dir ) or die "can't opendir $bak_dir: $!";

    while ( defined ( my $filename = readdir ( DIR ) ) ) {
        # if $filename is . or .. do not remove it
            if ( $filename !~ /\./ ) { # if this isn't there, you're dead
            # if $filename is older than $rotation_days then delete it
            my @filename_parts = split ( "-", $filename ); # to get epoch sec
            # allowed age of backups
            my $allowed_age = $since_epoch - ( 60 * 60 * 24 * $rotate_days );
            # if the last part of $filename < allowed age
            if ( ( $filename_parts[6] < $allowed_age ) && ($filename ne "") ) {
                # delete it
                my $zmrmtreestat = rmtree ( "$bak_dir/$filename" );
                # print the status of removing
                if ( $zmrmtreestat ) {
                    print $res_fh "Rotating Backup: Removed $bak_dir/$filename\n";
                }
                else {
                    print $res_fh "Rotating Backup: Can't delete $filename\n";
                }
            }
        }
    }
    closedir ( DIR );
}

# Send to remote system
if ( $send_remote ) {
    # Backup Zimbra using "rsync"
    my $rem_rsync_obj = File::Rsync->new ( {
        'rsync-path'    => $rsync,
        'archive'       => 1,
        'recursive'     => 1,
        'links'         => 1,
        'hard-links'    => 1,
        'keep-dirlinks' => 1,
        'perms'         => 1,
        'owner'         => 1,
        'group'         => 1,
        'devices'       => 1,
        'times'         => 1
    } );
    my $destination =
$ssh_server.':'.$remote_path.'/'.$current_time.'-'.$since_epoch;
    my $zmremrsyncstat = $rem_rsync_obj->exec ( {
        src     =>  "$backup_dir/",
        dest    =>  "$destination"
    } );

    if ( $zmremrsyncstat ) {
        print $res_fh "Remote Rsync: Successfully created $destination\n";
    }
    else {
        print $res_fh "Remote Rsync: Some Problem Occurred. Please check.\n";
    }
}

print $res_fh "The backup took: ", time ( ) - $since_epoch, " seconds\n";

# Send email report
if ( $send_result ) {
    # send results by email
    my $mailer = Mail::Mailer->new ( "sendmail" );
    $mailer->open( {
        'From'      =>  $from_email,
        'To'        =>  $to_email,
        'Cc'        =>  $cc_email,
        'Bcc'       =>  $bcc_email,
        'Subject'   =>  'Result of zimbraColdBackup'
    } ) or die "Can't open: $!\n";
    print $mailer $result;
    $mailer->close();
}

# print results on std output
print $result;



NB: This script uses Mail::Mailer to send a notification using sendmail. You should make sure that sendmail is installed on your system and that it is not set to start at boot otherwise you'll have a conflict with the Zimbra MTA not starting.

A Simple Shell Script Method

The following script can be called from the command line or crontab, and relies only on rsync, tar, and a scriptable ftp client. I used ncftp but you can use others and modify the syntax accordingly. This script was written and tested in Ubuntu 6.06 LTS server. I cannot confirm if it requires any modification to work in other distros but would appreciate feedback if necessary to make it more general.

#!/bin/bash
 
# Zimbra Backup Script
# Requires ncftp to run
# This script is intended to run from the crontab as root
# Date outputs and su vs sudo corrections by other contributors, thanks, sorry I don't have names to attribute!
# Free to use and free of any warranty!  Daniel W. Martin, 5 Dec 2008

 
# Outputs the time the backup started, for log/tracking purposes
echo Time backup started = $(date +%T)
before="$(date +%s)"

# Live sync before stopping Zimbra to minimize sync time with the services down
# Comment out the following line if you want to try single cold-sync only
rsync -avHK --delete /opt/zimbra/ /backup/zimbra

# which is the same as: /opt/zimbra /backup 
# Including --delete option gets rid of files in the dest folder that don't exist at the src 
# this prevents logfile/extraneous bloat from building up overtime.

# Now we need to shut down Zimbra to rsync any files that were/are locked
# whilst backing up when the server was up and running.
before2="$(date +%s)"

# Stop Zimbra Services
su - zimbra -c"/opt/zimbra/bin/zmcontrol stop"
sleep 15

# Kill any orphaned Zimbra processes
ORPHANED=`ps -u zimbra -o "pid="` && kill -9 $ORPHANED

# Only enable the following command if you need all Zimbra user owned
# processes to be killed before syncing
# ps auxww | awk '{print $1" "$2}' | grep zimbra | kill -9 `awk '{print $2}'`
 
# Sync to backup directory
rsync -avHK --delete /opt/zimbra/ /backup/zimbra

# Restart Zimbra Services
su - zimbra -c "/opt/zimbra/bin/zmcontrol start"

# Calculates and outputs amount of time the server was down for
after="$(date +%s)"
elapsed="$(expr $after - $before2)"
hours=$(($elapsed / 3600))
elapsed=$(($elapsed - $hours * 3600))
minutes=$(($elapsed / 60))
seconds=$(($elapsed - $minutes * 60))
echo Server was down for: "$hours hours $minutes minutes $seconds seconds"

# Create a txt file in the backup directory that'll contains the current Zimbra
# server version. Handy for knowing what version of Zimbra a backup can be restored to.
su - zimbra -c "zmcontrol -v > /backup/zimbra/conf/zimbra_version.txt"
# or examine your /opt/zimbra/.install_history

# Display Zimbra services status
echo Displaying Zimbra services status...
su - zimbra -c "/opt/zimbra/bin/zmcontrol status"
 
# Create archive of backed-up directory for offsite transfer
# cd /backup/zimbra
umask 0177
tar -zcvf /tmp/mail.backup.tgz -C /backup/zimbra .
 
# Transfer file to backup server
ncftpput -u <username> -p <password> <ftpserver> /<desired dest. directory> /tmp/mail.backup.tgz

rm /tmp/mail.backup.tgz

# Outputs the time the backup finished
echo Time backup finished = $(date +%T)

# Calculates and outputs total time taken
after="$(date +%s)"
elapsed="$(expr $after - $before)"
hours=$(($elapsed / 3600))
elapsed=$(($elapsed - $hours * 3600))
minutes=$(($elapsed / 60))
seconds=$(($elapsed - $minutes * 60))
echo Time taken: "$hours hours $minutes minutes $seconds seconds"

One further note: I have observed some odd behavior in this and other scripts that, when run from the command line work flawlessly, but when run from crontab the script may get ahead of itself and, for example, try to ftp the file before tar is done creating it; resulting in a useless backup. Loading the script into crontab with the parameters to create a log file, for example

. /etc/zimbra.backup > /temp/zbackup.log 2>&1

seems to solve this problem (while creating the log, or showing the output on the screen, the script seems to follow the sequence more carefully), while giving you a line-by-line record of the backup procedure. In my installation with just over 3GB backed up, the logfile is 2.5 mb and is overwritten each night.

NB You may find that using su on your operating system has problems and some services don't start or stop correctly. If that's the case use 'sudo -u zimbra' in the following format for the commands:

sudo -u zimbra zmcontrol start

A Simple Shell Script Method like above, but with rsync over ssh

#!/bin/bash

# Zimbra Backup Script
# Requires that you have ssh-keys: https://help.ubuntu.com/community/SSHHowto#Public%20key%20authentication
# This script is intended to run from the crontab as root
# Date outputs and su vs sudo corrections by other contributors, thanks, sorry I don't have names to attribute!
# Free to use and free of any warranty!  Daniel W. Martin, 5 Dec 2008
## Adapted for rsync over ssh instead of ncftp by Ace Suares, 24 April 2009 (Ubuntu 6.06 LTS)

# the destination directory for local backups
DESTLOCAL=/backup/backup-zimbra
# the destination for remote backups
DESTREMOTE="yourserver:/backup/backup-zimbra"

# Outputs the time the backup started, for log/tracking purposes
echo Time backup started = $(date +%T)
before="$(date +%s)"
# a backup dir on the local machine. This will fill up over time!
BACKUPDIR=$DESTLOCAL/$(date +%F-%H-%M-%S)

# Live sync before stopping Zimbra to minimize sync time with the services down
# Comment out the following line if you want to try single cold-sync only
rsync -avHK --delete --backup --backup-dir=$BACKUPDIR /opt/zimbra/ $DESTLOCAL/zimbra

# which is the same as: /opt/zimbra /backup 
# Including --delete option gets rid of files in the dest folder that don't exist at the src 
# this prevents logfile/extraneous bloat from building up overtime.
# the backupdir will hold all files that changed or where deleted during the previous backup

# Now we need to shut down Zimbra to rsync any files that were/are locked
# whilst backing up when the server was up and running.
before2="$(date +%s)"

# Stop Zimbra Services
/etc/init.d/zimbra stop
#su - zimbra -c"/opt/zimbra/bin/zmcontrol stop"
#sleep 15
# Kill any orphaned Zimbra processes
#kill -9 `ps -u zimbra -o "pid="`
pkill -9 -u zimbra

# Only enable the following command if you need all Zimbra user owned
# processes to be killed before syncing
# ps auxww | awk '{print $1" "$2}' | grep zimbra | kill -9 `awk '{print $2}'`

# Sync to backup directory
rsync -avHK --delete --backup --backup-dir=$BACKUPDIR /opt/zimbra/ $DESTLOCAL/zimbra

# Restart Zimbra Services
#su - zimbra -c "/opt/zimbra/bin/zmcontrol start"
/etc/init.d/zimbra start

# Calculates and outputs amount of time the server was down for
after="$(date +%s)"
elapsed="$(expr $after - $before2)"
hours=$(($elapsed / 3600))
elapsed=$(($elapsed - $hours * 3600))
minutes=$(($elapsed / 60))
seconds=$(($elapsed - $minutes * 60))
echo SERVER WAS DOWN FOR: "$hours hours $minutes minutes $seconds seconds"

# Create a txt file in the backup directory that'll contains the current Zimbra
# server version. Handy for knowing what version of Zimbra a backup can be restored to.
# su - zimbra -c "zmcontrol -v > $DESTLOCAL/zimbra/conf/zimbra_version.txt"
# or examine your /opt/zimbra/.install_history

# Display Zimbra services status
echo Displaying Zimbra services status...
su - zimbra -c "/opt/zimbra/bin/zmcontrol status"
# /etc/init.d/zimbra status # seems not to work
# backup the backup dir (but not the backups of the backups) to remote
rsync -essh -avHK --delete-during $DESTLOCAL/zimbra $DESTREMOTE

# Outputs the time the backup finished
echo Time backup finished = $(date +%T)

# Calculates and outputs total time taken
after="$(date +%s)"
elapsed="$(expr $after - $before)"
hours=$(($elapsed / 3600))
elapsed=$(($elapsed - $hours * 3600))
minutes=$(($elapsed / 60))
seconds=$(($elapsed - $minutes * 60))
echo Time taken: "$hours hours $minutes minutes $seconds seconds"

# end

Backup Shell Script with Compressed & Encrypted Archives

This script has following features:

  • Easy to use!
  • Backups with or without strong encryption!
  • Compressed archives
  • Optional Off-site copying of archives after creation
  • MD5 checksums for integrity checks of archives
  • Weekly backup rotation - 1 Full & 6 Diff's per rotation
  • Email report on Full backup
  • Email notifications on errors
  • Backup file lists (attached to weekly full backup report)
  • Installer & Setup option for quick deployment (install needed software and setup env e.g. ssh pki auth and cronjobs)


You can follow the development and find the latest info about usage and so on in the zimbra forum under the thread "[Yet Another Backup Script Community Version]" To download a current version of this script go to the forum thread there you will find a link to the file in the first post. If you need any help you can contact me in the forum, I would be happy to help!

#!/bin/bash
## *** Info ***
# USAGE:    -h or --help for help & usage.
#           -f or --full for Full backup.
#           -d or --diff for Diff backup.
#           -V or --version for version info.
#           --INSTALL	 for script install and setup.
#
# This is a backup script for the FOSS version of Zimbra mail server.
# The script is free and open source and for use by anyone who can find a use for it.
#
# THIS SCRIPT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
# HOLDERS AND/OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS DOCUMENT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# CONTRIBUTORS:
# heinzg of osoffice.de (original author)
# Quentin Hartman of Concentric Sky, qhartman@concentricsky.com (refactor and cleanup)
#
# What this script does:
# 1. Makes daily off-line backups, at a service downtime of ~ < 2 min.
# 2. Weekly backup cycle - 1 full backup & 6 diffs.
# 3. Predefined archive sizes, for writing backups to CD or DVD media...
# 4. Backup archive compression.
# 5. Backup archive encryption.
# 6. Backup archive integrity checks and md5 checksums creation.
# 7. Automated DR - Off-site copy of backup archives via ssh.
# 8. Install and setup function for needed software (Ubuntu Systems only)
# 9. Weekly eMail report & eMail on error - including CC address.
#
# This script makes use of following tools:
# apt-get, cron, dar, dpkg, mailx, md5sum, rsync, ssh, uuencode, wget, zimbra mta.
#
# We have opted to use a pre-sync directory to save on "down time", but this 
# causes one to have huge additional space usage.
# But hard drives are cheep today!
#
# What is still to come or needs work on:
# 1. Recovery option
# 2. Better documentation

##------- CONFIG -------#
# Edit this part of the script to fit your needs.

#--- Directories ---#
# Please add the trailing "/" to directories!
ZM_HOME=/opt/zimbra/	# where zimbra lives
SYNC_DIR=/tmp/fakebackup/	# intermediate dir for hot/cold syncs. must have at least as much free space as ZM_HOME consumes
ARCHIVEDIR=/Backup/zimbra_dars/	# where to store final backups
TO_MEDIA_DIR=/Backup/burn/	# where to put fulls for archiving to media

#--- PROGRAM OPTIONS ---# 
RSYNC_OPTS="-aHK --delete --exclude=*.pid" # leave these unless you are sure you need something else

#--- ARCHIVE NAMES ---#
BACKUPNAME="Zimbra_Backup"	# what you want your backups called
FULL_PREFIX="FULL"	# prefix used for full backups
DIFF_PREFIX="DIFF"	# prefix used for differential backups
BACKUPDATE=`date +%d-%B-%Y`	# date format used in archive names
BACKUPWEEK=`date +%W`	# Week prefix used for backup weekly rotation and naming

#--- ARCHIVE SIZE ---#
ARCHIVESIZE="4395M"	# storage media size, for full-backup archiving
COMPRESS="9"		# valid answers are 1 - 9 ( 9 = best )

#--- Encryption Options ---#
CRYPT="yes"		# valid answers are "yes" or "no"
PASSDIR=/etc/`basename $0`/ # the directory the encryption hash is stored in. 
PASSFILE="noread"	# the file containing the password hash

#--- Log Settings ---#
EMAIL="your@mailaddress.local"	# the address to send logs to
EMAILCC=""				# another address to send to
LOG="/var/log/zim_backup.log"	# log location

#--- SSH REMOTE DR COPY ---#
# This option will secure copy your archives to a remote server via 'scp'
DRCP="no"		# valid answers are "yes" or "no" 
SSHUSER="you"	# recommend creating a user on the remote machine just for transferring backups	
SSHKEY="rsa"	# recommended answers are "rsa" or "dsa" but "rsa1" is also valid.
REMOTEHOST="remote.server.fqdn"	# can use IP too
REMOTEDIR="/tmp/"	# where you want your backups saved.

#--- Use Hacks? ---#
# Built in hacks to fix common problems
#Hack to start Stats, even run zmlogprocess if needed
STATHACK="yes" 		# valid answers are "yes" or "no"


## ~~~~~!!!! SCRIPT RUNTIME !!!!!~~~~~ ##
# Best you don't change anything from here on, 
# ONLY EDIT IF YOU KNOW WHAT YOU ARE DOING

Snapshots

While the above three methods can be used on a rotating fashion, their mainly full copies; as anyone with a 20TB store knows, backups take up space.

Thus, this section is devoted to reducing storage needed through incrementalish snapshots.

-Labeled 'ish' because this is nothing like the NE method of hot/live backups using redologs to restore to any given second.

-In short, so we don't confuse it with NE, please don't say "my incrementals aren't working" in the forums without first mentioning that you're using a FOSS method.

(Hence this is labled 'snapshots' to cut down on some confusion.)

Utilities to help you make rotating snapshots:

rsnapshot

rdiff-backup

An rsync script

Another script being worked out: http://www.zimbra.com/forums/showthread.php?threadid=15275

Another: http://www.zimbra.com/forums/showthread.php?threadid=15963

Emergency Repairs

Preparing to Back Up

Before we begin, make sure that you are logged in as a user that can perform the tasks outlined here.

It is always good practice to backup your copy of Zimbra in the event of unforeseen circumstances.

To prevent changes to any Zimbra databases during the backup processes you may wish to use:

>su zimbra
>zmcontrol stop

to terminate Zimbra.

If you get some kind of error, you may want to make sure that Zimbra has completly stopped by running:

>ps auxww | grep zimbra

and kill any left over processes such as the log.

Alternatively as root you could run the following command to kill all Zimbra user owned processes instantly (use wisely):

>ps auxww | awk '{print $1" "$2}' | grep zimbra | kill -9 `awk '{print $2}'`

Backing Up

Make sure that the copy location has enough space to support your backup copy (i.e. the /tmp folder probably isn't the best location).

Since all of the components Zimbra needs are stored in the Zimbra folder itself, you can simply copy the folder to a safe location.

It may be possible to create a cron job to do these tasks automatically.

Copy Command: cp -Rp /opt/zimbra [location path]

Depending on your hardware and the amount of data contained in your Zimbra installation, this process can take a while.

Note: It is a very good idea to tag your installation with the version/build of zimbra that will be backed up (ie 3.0.0_GA_156) and the date of backup. You'll need this later.

Restoring

Before restoring, you should make sure that all of the processes accociated with the damaged/failed Zimbra installation are terminated. Failure to terminate all of the processes could have dire consquences. See "Preparing to Backup" for additional info.

====Rename your "broken" Zimbra installation.'

You may be able to scavenge data, if needed. If you simply do not want the old data, you can skip this part.

>mv /opt/zimbra [new location i.e. /tmp/zimbra-old]

You may want to move it completly out of the /opt folder just to be safe.

Copy your backup Zimbra installation to the /opt folder and name it "zimbra".

>cp -rp [location of backup] /opt
>mv /opt/[backup name] /opt/zimbra

Restore to Existing/Backup Zimbra Server

In the event of a failure, you can either restore your /opt/zimbra folder to a server that is not currently running Zimbra and download a dummy copy of Zimbra and run an upgrade in order to clean everything up and make it run correctly again (see next section), or you may restore the backup to an existing Zimbra server. This will only work if the existing server is running the EXACT SAME VERSION of Zimbra as the backup you want to restore. Also, this has been tested and seems to work well with CE 4.5.8, but did not work with 4.5.7. This may be, for example, a backup email server that you want to always keep current with last night's backup, so it can replace the production server on short notice in the event of a disaster.

Simply set up your backup server identical to your production server (preferably the same OS, but necessarily the exact same version of Zimbra). Any modifications you made or packages you added for your production server with regards to extra anti-spam protection, etc., should also be added to this server. Shut down Zimbra on the backup server. Copy /opt/zimbra from your backup to the backup server.

chown -R zimbra:zimbra /opt/zimbra
/opt/zimbra/libexec/zmfixperms

Start Zimbra. Everything should work. The advantage to this method is that you can retain all your customizations (anti-spam modifications, for example) that would otherwise have been lost in the "upgrade" method. Also, this allows you to use a script to keep a backup server current without having to reinstall Zimbra after each time the backup server is made current, or before putting the backup server into production in the event of a failure.

Downloading a Dummy Copy of Zimbra

Now, we need to know what build/version of zimbra you were running. If you followed the backup instructions above, then the backup folder should be tagged with the version/build you have backed up.

You need to download the full install of the Zimbra version you were running. You may find all Zimbra releases at: Sourceforge.

If you don't know your version number, you can find it by:

Method 1 - view install_history file.

cat /opt/zimbra/.install_history

Method 2 - dont think this will work unless you did a bunch of chroots.

zmcontrol -v

Both of the above listed methods were from this forum post

Installing the Dummy Copy of Zimbra

Once you have downloaded the tar file, you will need to uncompress it by:

>tar -xvzf [name of file].tgz

This will create a folder in the directory named "zcs", cd to it and run the install script:

>cd zcs
>./install.sh

WARNING: Do not run the script with the -u option. You will remove all of your backup data & you must run the script as root, NOT ZIMBRA.

The script will remove the existing packages, and install them again. The script will attempt to stop Zimbra Services and "UPGRADE FAILED - exiting". This is okay, simply rerun the script, and it will install normally.

If you experence error 389, -1, connection refused errors, please search the Forums. These errors are covered extensivly.

Resetting Permissions

If you are up and running now, you may have one more hurdle to overcome: permissions.

You may need to reset the permissions on the message store by running the following:

>/opt/zimbra/libexec/zmfixperms

This is potentially a dangerous suggestion, but if you have trouble getting tomcat to start even after you run zmfixperms, try running (worked for ZCS 4.5.7 CE)

chown -R zimbra:zimbra /opt/zimbra

Of course, you must run

/opt/zimbra/libexec/zmfixperms

again after that. It appears that zmfixperms is supposed to chown zimbra:zimbra on something, but it misses it. This way, you chown EVERYTHING zimbra:zimbra, and zmfixperms puts back things that need to be owned as root, postfix, etc.

Disaster Recovery

In the unfortunate event of losing your complete server or installation, the following will get you up and running.

This has been tested successfully on v5.0.5

  • The machine you are recovering to must have the same hostname as the original machine.
  • Once you have your OS and all pre-requisites installed. Download and install Zimbra as normal, using the same zimbra version as the backup. If it is a new server, you can install using install.sh -s to install just the packages to create the users and programs before recreating the old installation/
  • Once Zimbra is installed, stop all Zimbra services and move/rename the /opt/zimbra folder:
sudo -u zimbra /opt/zimbra/bin/zmcontrol shutdown
mv /opt/zimbra /tmp/zimbra-old
  • Uncompress the most recent backup file to the /opt/zimbra folder
mkdir /opt/zimbra
tar zxvf [backup file] -C /opt/zimbra

or if you prefer...

tar zxvf [backup file] -C /tmp/zimbra-backup
cp -Rp /tmp/zimbra-backup /opt/zimbra
  • Fix the Zimbra permissions
chown -R zimbra:zimbra /opt/zimbra
/opt/zimbra/libexec/zmfixperms
  • Restart all Zimbra services
sudo -u zimbra /opt/zimbra/bin/zmcontrol startup
zmcontrol startup

You should now be able to access Zimbra as normal. If not, you may need to "upgrade" zimbra to set up the old configuration, for example if you have zimbra listening on a web port other than 80. install.sh from the directory you extracted the zimbra install to. This will also restart services when completed, so you should be up and running

Verified Against: ZCS 4.0, 4.5.7 and 5.0.5 Date Created: 5/16/2006
Article ID: https://wiki.zimbra.com/index.php?title=Open_Source_Edition_Backup_Procedure Date Modified: 2015-07-11



Try Zimbra

Try Zimbra Collaboration with a 60-day free trial.
Get it now »

Want to get involved?

You can contribute in the Community, Wiki, Code, or development of Zimlets.
Find out more. »

Looking for a Video?

Visit our YouTube channel to get the latest webinars, technology news, product overviews, and so much more.
Go to the YouTube channel »

Jump to: navigation, search