My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Ask questions about your setup or get help installing ZCS server (ZD section below).
4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

ZIMBRA BACKUP
THERE ARE VARIOUS METHODS OF BACKUP THAT CAN BE UTILIZED BUT THESE ARE THE ONES I WILL BE USING:




BACKUP TO LOCAL FOLDER USING RSYNC

BACKUP INDIVIDUAL MAILBOXES

BACKUP USING LVM SNAPSHOTS


IF I HAVE TIME, I WILL ALSO EXPLORE THE SETUP OF AN ADDITIONAL SERVER TO SERVE AS A HOT-SPARE SO-TO-SPEAK. I'D LIKE TO SEE A BACKUP SERVER CONFIGURED TO RECEIVE BACKUPS FROM THE PRODUCTION SERVER AND IN THE EVENT THE PRODUCTION SERVER GOES DARK, SPIN UP THE BACKUP SERVER TO BE ITS REPLACEMENT.
FOR THE 1ST METHOD OF USING RSYNC, THERE IS ONE MAJOR CATCH USING RSYNC ALONE IN THAT YOU CANNOT BACKUP FILES CURRENTLY IN USE. THAT MEANS YOU HAVE TO SHUTDOWN THE SERVICES IN ORDER TO GET A COMPLETE BACKUP. WITH THIS IN MIND, MY SOLUTION IS TO UTILIIZE TWO SCRIPTS. THE 1ST SCRIPT WILL BACKUP WHAT IT CAN WHILE THE SERVER IS "ONLINE" AND THE 2ND SCRIPT WILL RUN DURING OFF-HOURS TO SHUTDOWN THE SERVICES (MAKE IT OFFLINE) AND PERFORM A COMPLETE BACKUP.
THE ONLINE SCRIPT WILL BE SCHEDULED TO RUN MULTIPLE TIMES THROUGHOUT THE DAY AND WILL NOT CAUSE ANY DOWNTIME.
THE OFFLINE SCRIPT WILL BE SCHEDULED ONCE PER DAY AT A TIME THAT WILL CAUSE THE LEAST AMOUNT OF IMPACT BECAUSE THE SERVER WILL GO OFFLINE FOR ABOUT 3 TO 5 MINUTES. IT WILL THEN COMPRESS THE BACKUP INTO A SINGLE ARCHIVE AND MOVE IT TO AN OFFSITE SERVER.
MY OFFSITE STORAGE WILL BE ON A WINDOWS 2008 SERVER. THE 1ST THING TO DO WILL BE THE CONFIGURATION OF THE WINDOWS SERVER TO ALLOW THE UBUNTU SERVER TO CONNECT AND MANAGE FILES.



BACKUP - RSYNC WHILE ONLINE
RSYNC-ONLINE.SH



#!/BIN/BASH

#############################################

## NAME : RSYNC-ONLINE.SH

## VERSION : 1.1

## DATE : 2011-11-04

## AUTHOR : LHAMMONDS

## COMPATIBILITY : UBUNTU SERVER 10.04.3 - 10.04.4 LTS, ZIMBRA 7.1.2 - 7.2.0 OSE

## PURPOSE : PARTIAL BACKUP WHILE ZIMBRA IS ONLINE.

## RUN FREQUENCY : SEVERAL TIMES THROUGHOUT THE DAY.

## EXIT CODES : (IF MULTIPLE ERRORS, VALUE IS THE ADDITION OF CODES)

## 0 = SUCCESS

## 1 = RSYNC FAILURE

################ CHANGE LOG #################

## DATE WHO WHAT WAS CHANGED

## ---------- --- ----------------------------

## 2011-10-21 LTH CREATED SCRIPT.

## 2011-11-04 LTH MOVED COMMON VARIABLES AND FUNCTIONS TO EXTERNAL FILE.

#############################################
## IMPORT COMMON VARIABLES AND FUNCTIONS. ##

SOURCE /VAR/SCRIPTS/COMMON/STANDARD.CONF
LOGFILE="${TEMPDIR}/RSYNC.LOG"

TARGET="${BACKUPDIR}/ZIMBRA"

LOCKFILE="${TEMPDIR}/RSYNC.LOCK"

ERRORFLAG=0

RETURNVALUE=0
#######################################

## FUNCTIONS ##

#######################################
FUNCTION F_CLEANUP()

{

IF [ -F ${LOCKFILE} ];THEN

## REMOVE LOCK FILE SO OTHER RSYNC JOBS CAN RUN.

RM ${LOCKFILE} 1>/DEV/NULL 2>&1

FI

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - ONLINE RSYNC BACKUP EXIT CODE: ${ERRORFLAG}" >> ${LOGFILE}

}
#######################################

## MAIN PROGRAM ##

#######################################

IF [ -F ${LOCKFILE} ]; THEN

## RSYNC LOCK FILE DETECTED. ABORT SCRIPT.

F_SENDMAIL "ONLINE RSYNC BACKUP ABORTED - LOCK FILE" "THIS SCRIPT TRIED TO RUN BUT DETECTED THE LOCK FILE: ${LOCKFILE}NNPLEASE CHECK TO MAKE SURE THE FILE DOES NOT REMAIN WHEN RSYNC IS NOT ACTUALLY RUNNING."

EXIT 1

ELSE

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` ${SCRIPTNAME}" > ${LOCKFILE}

FI
ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - ONLINE RSYNC BACKUP MODE STARTED." >> ${LOGFILE}
## OUTPUT THE CURRENT VERSION TO A TEXT FILE WHICH WILL BE INCLUDED IN THE BACKUP.

## NOTE: YOU CAN ALSO VIEW /OPT/ZIMBRA/.INSTALL_HISTORY

SU - ZIMBRA -C "ZMCONTROL -V > ${ZIMBRADIR}/CONF/ZIMBRA_VERSION.TXT"
## RSYNC WILL COPY WHAT IT CAN TO THE TARGET LOCATION.

RSYNC -APOGHK --DELETE --EXCLUDE=*.PID ${ZIMBRADIR} ${TARGET} 1>/DEV/NULL 2>&1

RETURNVALUE=$?

IF [ ${RETURNVALUE} -NE 0 ]; THEN

## ERROR: SEND EMAIL NOTIFICATION.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- ERROR: ONLINE RSYNC FAILED. ${ZIMBRADIR} -> ${TARGET}" >> ${LOGFILE}

F_SENDMAIL "ONLINE RSYNC BACKUP FAILURE - RSYNC" "ERROR: ONLINE RSYNC FAILED. ${ZIMBRADIR} -> ${TARGET}, RETURN VALUE = ${RETURNVALUE}"

ERRORFLAG=${ERRORFLAG} + 1

FI

## DOCUMENT STATISTICS.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - DISK USAGE FOR BOTH SOURCE AND TARGET:" >> ${LOGFILE}

ECHO "`DU -SH ${ZIMBRADIR}`" >> ${LOGFILE}

ECHO "`DU -SH ${TARGET}`" >> ${LOGFILE}

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - ONLINE RSYNC BACKUP MODE COMPLETED." >> ${LOGFILE}
## PERFORM CLEANUP ROUTINE.

F_CLEANUP

## EXIT WITH THE COMBINED RETURN CODE VALUE.

EXIT ${ERRORFLAG}

4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

Backup - RSync while offline
Although this backup takes the services down, the RSync job just prior to taking the services down ensures the vast majority of the data is already backed up. The only thing that has to be done after the services are down is to copy the changes in the last minute and the files that could not be copied while the services were running.
The actual downtime is typically between 3 to 5 minutes of my server and I doubt it will require longer downtime time even as the data store increases.
rsync-offline.sh



#!/bin/bash

#############################################

## Name : rsync-offline.sh

## Version : 1.4

## Date : 2012-01-09

## Author : LHammonds

## Purpose : Complete backup while Zimbra is offline.

## Compatibility : Verified on Ubuntu Server 10.04.3 - 10.04.4 LTS, Zimbra 7.1.2 - 7.2.0 OSE

## Requirements : p7zip-full (if ARCHIVEMETHOD=tar.7z)

## Run Frequency : Once per day after hours.

## Exit Codes : (if multiple errors, value is the addition of codes)

## 0 = success

## 1 = rsync failure

## 2 = archive failure

## 4 = archive purge failure

## 8 = configuration error

## 16 = crontab backup error

## 32 = crontab restore warning

## 64 = mount warning

################ CHANGE LOG #################

## DATE WHO WHAT WAS CHANGED

## ---------- --- ----------------------------

## 2011-10-21 LTH Created script.

## 2011-10-28 LTH Added 7-Zip compression (gunzip optional)

## 2011-11-04 LTH Move common variables and funtions to external file.

## 2011-11-08 LTH Added zimbra subfolder to remote site for organization.

## 2012-01-09 LTH Bugfix for f_PurgeOldestArchive

#############################################
## Import common variables and functions. ##

source /var/scripts/common/standard.conf
LOGFILE="${TEMPDIR}/rsync.log"

TEMPLOG="${TEMPDIR}/rsync-offline-temp.$$"

LOCKFILE="${TEMPDIR}/rsync.lock"

TARGETDIR="${BACKUPDIR}/zimbra"

OFFSITEBACKDIR="${OFFSITEDIR}/zimbra"

ARCHIVEFILE="`date +%Y-%m-%d-%H-%M`_zimbra-backup.${ARCHIVEMETHOD}"

ZMCRONFILE="${TEMPDIR}/zimbra-crontab.$$"

ERRORFLAG=0
#######################################

## FUNCTIONS ##

#######################################

function f_PurgeOldestArchive()

{

## Purpose: Delete the oldest archive on the remote site.

## Return values:

## 0 = Success

## 1 = Cannot delete file

## 9 = Configuration error, path empty
## Variable Error Check. *

if [ ${OFFSITEBACKDIR} = "" ]; then

## Make darn sure the path is not empty since we do NOT

## want to start purging files from a random location.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Purge error: OFFSITEBACKDIR site variable is empty!" >> ${TEMPLOG}

return 9

fi

## Get the name of the oldest file.

OLDESTFILE=`ls -1t ${OFFSITEBACKDIR} | tail -1`

FILESIZE=`ls -la ${OFFSITEDIR}/${OLDFILE} | awk '{print $5}' | sed -e :a -e 's/(.*[0-9])([0-9]{3})/1,2/;ta'`

if [ "${OLDESTFILE}" = "" ]; then

## Error. Filename variable empty.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Purge error: OLDESTFILE variable is empty." >> ${TEMPLOG}

return 9

else

FILESIZE=`ls -lak "${OFFSITEBACKDIR}/${OLDESTFILE}" | awk '{ print $5 }' | sed -e :a -e 's/(.*[0-9])([0-9]{3})/1,2/;ta'`

echo "`date +%Y-%m-%d_%H:%M:%S` --- Purging old file: ${OFFSITEBACKDIR}/${OLDESTFILE}, Size = ${FILESIZE} kb" >> ${TEMPLOG}

rm "${OFFSITEBACKDIR}/${OLDESTFILE}"

if [ -f "${OFFSITEBACKDIR}/${OLDESTFILE}" ]; then

## File still exists. Return error.

return 1

else

return 0

fi

fi

}
function f_cleanup()

{

echo "`date +%Y-%m-%d_%H:%M:%S` - Offline RSync backup exit code: ${ERRORFLAG}" >> ${TEMPLOG}

## Copy temporary log file into main log file.

cat ${TEMPLOG} >> ${LOGFILE}
if [ -f ${LOCKFILE} ];then

## Remove lock file so other rsync jobs can run.

rm ${LOCKFILE} 1>/dev/null 2>&1

fi

## Email the log to the administrator.

EMAILBODY=""

while read FILELINE; do

EMAILBODY=${EMAILBODY}${FILELINE}"
"

done
f_sendmail "Offline RSync Backup Log" "${EMAILBODY}"

if [ -f ${TEMPLOG} ]; then

rm ${TEMPLOG}

fi

}
function f_emergencyexit()

{

## Purpose: Exit script as cleanly as possible.

## Parameter #1 = Error Code

f_cleanup

exit $1

}
#######################################

## MAIN PROGRAM ##

#######################################

if [ -f ${LOCKFILE} ]; then

# rsync lock file detected. Abort script.

f_sendmail "Offline RSync Backup Aborted - Lock File" "This script tried to run but detected the lock file: ${LOCKFILE}

Please check to make sure the file does not remain when rsync is not actually running."

exit 1

else

echo "`date +%Y-%m-%d_%H:%M:%S` ${SCRIPTNAME}" > ${LOCKFILE}

fi
echo "`date +%Y-%m-%d_%H:%M:%S` - Offline RSync backup started." >> ${TEMPLOG}
## If the 7-Zip archive method is specified, make sure the package is installed.

if [ "${ARCHIVEMETHOD}" = "tar.7z" ]; then

if [ ! -f "/usr/bin/7za" ]; then

## Required package (7-Zip) not installed.

echo "`date +%Y-%m-%d_%H:%M:%S` - CRITICAL ERROR: 7-Zip package not installed. Please install by typing 'aptitude -y install p7zip-full'" >> ${TEMPLOG}

ERRORFLAG=2

f_emergencyexit ${ERRORFLAG}

fi

fi
echo "`date +%Y-%m-%d_%H:%M:%S` --- Partition status:" >> ${TEMPLOG}

df -h >> ${TEMPLOG}
## Output the current version to a text file to be included in the backup.

## NOTE: You can also view /opt/zimbra/.install_history

su - zimbra -c "zmcontrol -v > ${ZIMBRADIR}/conf/zimbra_version.txt"
echo "`date +%Y-%m-%d_%H:%M:%S` --- Begin pre-shutdown rsync command." >> ${TEMPLOG}

rsync -apogHK --delete --exclude=*.pid ${ZIMBRADIR} ${TARGETDIR} 1>/dev/null 2>&1
## Backup the zimbra crontab schedule.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Backup and disable Zimbra crontab schedule." >> ${TEMPLOG}

crontab -u zimbra -l > ${ZMCRONFILE}

RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## Something went wrong with the backup of the crontab file.

## This error will be considered fatal and terminate the script.

f_sendmail "RSync Offline Backup Error - Crontab" "Could not backup crontab for the zimbra user account. RETURN VALUE = ${RETURNVALUE}"

ERRORFLAG=$((${ERRORFLAG} + 16))

f_emergencyexit ${ERRORFLAG}

else

## Backup successful, now disable the zimbra crontab schedule.

echo "" > ${TEMPDIR}emptyfile.$$

crontab -u zimbra ${TEMPDIR}emptyfile.$$

rm ${TEMPDIR}emptyfile.$$ 1>/dev/null 2>&1

## Add a copy of the crontab file to the Zimbra folder to be backed up.

cp ${ZMCRONFILE} ${ZIMBRADIR} 1>/dev/null 2>&1

fi
StartTime="$(date +%s)"
## Stop Zimbra Services.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Stopping Zimbra services." >> ${TEMPLOG}

/etc/init.d/zimbra stop 1>/dev/null 2>&1
## Kill any orphaned Zimbra processes.

pkill -9 -u zimbra 1>/dev/null 2>&1
echo "`date +%Y-%m-%d_%H:%M:%S` --- Space consumed in ${ZIMBRADIR} = `du -sh ${ZIMBRADIR} | awk '{ print $1 }'`" >> ${TEMPLOG}
## Now that Zimbra is offline, rsync can quickly copy all remaining files to the backup target.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Begin post-shutdown rsync command." >> ${TEMPLOG}

rsync -apogHK --delete --exclude=*.pid ${ZIMBRADIR} ${TARGETDIR} 1>/dev/null 2>&1

RETURNVALUE=$?
## Quickly start the Zimbra services.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Starting Zimbra services." >> ${TEMPLOG}

/etc/init.d/zimbra start 1>/dev/null 2>&1
if [ ${RETURNVALUE} -ne 0 ]; then

## rsync command failed. Send warning email.

f_sendmail "RSync Offline Backup Failure - rsync" "rsync failed with return value of ${RETURNVALUE}"

ERRORFLAG=$((${ERRORFLAG} + 1))

fi
## Calculates downtime of Zimbra services.

FinishTime="$(date +%s)"

ElapsedTime="$(expr ${FinishTime} - ${StartTime})"

Hours=$((${ElapsedTime} / 3600))

ElapsedTime=$((${ElapsedTime} - ${Hours} * 3600))

Minutes=$((${ElapsedTime} / 60))

Seconds=$((${ElapsedTime} - ${Minutes} * 60))
echo "`date +%Y-%m-%d_%H:%M:%S` --- Zimbra downtime: ${Hours} hour(s) ${Minutes} minute(s) ${Seconds} second(s)" >> ${TEMPLOG}
## Restore the zimbra crontab schedule.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Restore Zimbra crontab schedule." >> ${TEMPLOG}

crontab -u zimbra ${ZMCRONFILE}

RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## Could not restore the zimbra crontab schedule.

## This is considered a non-fatal error and the script will continue.

f_sendmail "Offline RSync Backup Warning - Crontab" "Could not restore the zimbra crontab schedule using ${ZMCRONFILE} RETURN VALUE = ${RETURNVALUE}"

ERRORFLAG=$((${ERRORFLAG} + 32))

else

## Zimbra crontab schedule restored. Remove temp file.

rm ${ZMCRONFILE}

fi
echo "`date +%Y-%m-%d_%H:%M:%S` --- Space consumed in ${TARGETDIR} = `du -sh ${TARGETDIR} | awk '{ print $1 }'`" >> ${TEMPLOG}
## Show status of Zimbra services.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Status of Zimbra services:" >> ${TEMPLOG}

su - zimbra -c "zmcontrol status" >> ${TEMPLOG}
## Compress the backup into a single file based on archive method specified.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Compressing archive: ${TEMPDIR}/${ARCHIVEFILE}" >> ${TEMPLOG}

case "${ARCHIVEMETHOD}" in

tar.7z)

tar -cpf - ${TARGETDIR} | 7za a -si -mx=9 -w${TEMPDIR} ${TEMPDIR}/${ARCHIVEFILE} 1>/dev/null 2>&1

## Restore using one of the following commands (do not uncomment, only for notation):

## 7za x -so -w/tmp ${TEMPDIR}/${ARCHIVEFILE} | tar -C / -xf -

## 7za x -so -w/tmp ${TEMPDIR}/${ARCHIVEFILE} | tar -C ${TEMPDIR}/restore --strip-components=1 -xf -

;;

tgz)

tar -cpzf ${TEMPDIR}/${ARCHIVEFILE} ${TARGETDIR} 1>/dev/null 2>&1

## Restore using one of the following commands (do not uncomment, only for notation):

## tar -C / -xzf ${TEMPDIR}/${ARCHIVEFILE}

## tar -C ${TEMPDIR}/restore --strip-components=1 -xzf ${TEMPDIR}/${ARCHIVEFILE}

;;

*)

tar -cpzf ${TEMPDIR}/${ARCHIVEFILE} ${TARGETDIR} 1>/dev/null 2>&1

;;

esac
RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## tar command failed. Send warning email.

f_sendmail "Offline RSync Backup Failure - tar" "tar failed with return value of ${RETURNVALUE}"

ERRORFLAG=$((${ERRORFLAG} + 2))

fi
## Mount the Windows share folder. ##

f_mount

sleep 2

if [ ! -f ${OFFSITETESTFILE} ]; then

## Could not find expected file on remote site. Assuming failed mount.

ERRORFLAG=$((${ERRORFLAG} + 64))

f_sendmail "Offline RSync Backup - Win Mount Error" "${HOSTNAME} could not detect ${OFFSITETESTFILE}"

else

## Remote site is available.

FREESPACE=`df -k ${OFFSITEDIR} | grep ${OFFSITEDIR} | awk '{ print $3 }'`

BACKUPSIZE=`ls -lak "${TEMPDIR}/${ARCHIVEFILE}" | awk '{ print $5 }'`
## Make sure space is available on the remote server to copy the file.

if [ ${FREESPACE} -lt ${BACKUPSIZE} ]; then

## Not enough free space available. Purge existing backups until there is room.

ENOUGHSPACE=0

while [ ${ENOUGHSPACE} -eq 0 ]

do

f_PurgeOldestArchive

RETURNVALUE=$?

case ${RETURNVALUE} in

1)

## Cannot purge archives to free up space. End program gracefully.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Not enough free space on ${OFFSITEDIR} and cannot purge old archives. Script aborted." >> ${TEMPLOG}

## Stop and exit the script with an error code.

ERRORFLAG=$((${ERRORFLAG} + 4))

f_emergencyexit ${ERRORFLAG}

;;

9)

## Configuration error, end program gracefully.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Configuration problem. Script aborted." >> ${TEMPLOG}

## Stop and exit the script with an error code.

ERRORFLAG=$((${ERRORFLAG} + 8))

f_emergencyexit ${ERRORFLAG}

;;

esac

FREESPACE=`df -k ${OFFSITEDIR} | grep ${OFFSITEDIR} | awk '{ print $3 }'`

if [ ${FREESPACE} -gt ${BACKUPSIZE} ]; then

## Enough space is now available.

ENOUGHSPACE=1

else

## Not enough space is available yet.

ENOUGHSPACE=0

fi

done

fi
## Copy the backup to an offsite storage location.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Copying archive file to offsite location." >> ${TEMPLOG}

cp ${TEMPDIR}/${ARCHIVEFILE} ${OFFSITEBACKDIR}/${ARCHIVEFILE} 1>/dev/null 2>&1

if [ ! -f ${OFFSITEBACKDIR}/${ARCHIVEFILE} ]; then

## NON-FATAL ERROR: Copy command did not work. Send email notification.

echo "`date +%Y-%m-%d_%H:%M:%S` --- WARNING: Remote copy failed. ${OFFSITEBACKDIR}/${ARCHIVEFILE} does not exist!" >> ${TEMPLOG}

f_sendmail "Offline RSync Backup Failure - Remote Copy" "Remote copy failed. ${OFFSITEBACKDIR}/${ARCHIVEFILE} does not exist

Backup file still remains in this location: ${HOSTNAME}:${TEMPDIR}/${ARCHIVEFILE}"

else

## Remove local copy of the compressed backup file

rm ${TEMPDIR}/${ARCHIVEFILE}

fi

fi

## Unmount the Windows shared folder.

f_umount
## Calculate total time for backup.

FinishTime="$(date +%s)"

ElapsedTime="$(expr ${FinishTime} - ${StartTime})"

Hours=$((${ElapsedTime} / 3600))

ElapsedTime=$((${ElapsedTime} - ${Hours} * 3600))

Minutes=$((${ElapsedTime} / 60))

Seconds=$((${ElapsedTime} - ${Minutes} * 60))
echo "`date +%Y-%m-%d_%H:%M:%S` --- Total backup time: ${Hours} hour(s) ${Minutes} minute(s) ${Seconds} second(s)" >> ${TEMPLOG}

echo "`date +%Y-%m-%d_%H:%M:%S` - Offline RSync backup completed." >> ${TEMPLOG}
## Perform cleanup routine.

f_cleanup

## Exit with the combined return code value.

exit ${ERRORFLAG}


Example output in the log file:



2011-10-28_17:43:21 - Offline RSync backup started.

2011-10-28_17:43:21 --- Partition status:

Filesystem 1K-blocks Used Available Use% Mounted on

/dev/mapper/LVG-root 3842104 1467924 2179008 41% /

none 2025164 188 2024976 1% /dev

none 2030020 0 2030020 0% /dev/shm

none 2030020 296 2029724 1% /var/run

none 2030020 0 2030020 0% /var/lock

none 2030020 0 2030020 0% /lib/init/rw

none 3842104 1467924 2179008 41% /var/lib/ureadahead/debugfs

/dev/sda1 182331 33053 139550 20% /boot

/dev/mapper/LVG-bak 240306696 3333320 224766480 2% /var/backup

/dev/mapper/LVG-opt 120152260 3287176 110761636 3% /opt

/dev/mapper/LVG-temp 240306696 799184 227300616 1% /var/temp

2011-10-28_17:43:22 --- Begin pre-shutdown rsync command.

2011-10-28_17:45:10 --- Backup and disable Zimbra crontab schedule.

2011-10-28_17:45:10 --- Stopping Zimbra services.

2011-10-28_17:45:54 --- Space consumed in /opt/zimbra = 3.3G

2011-10-28_17:45:58 --- Begin post-shutdown rsync command.

2011-10-28_17:47:05 --- Starting Zimbra services.

2011-10-28_17:48:32 --- Zimbra downtime: 0 hour(s) 3 minute(s) 22 second(s)

2011-10-28_17:48:32 --- Restore Zimbra crontab schedule.

2011-10-28_17:48:33 --- Space consumed in /temp/zimbra = 3.4G

2011-10-28_17:48:35 --- Status of Zimbra services:

Host mail.mydomain.com

antispam Running

antivirus Running

ldap Running

logger Running

mailbox Running

mta Running

snmp Running

spell Running

stats Running

zmconfigd Running

2011-10-28_17:48:50 --- Compressing archive: /var/temp/2011-10-28_zmbackup.tar.7z

2011-10-28_18:10:09 --- Copying archive file to offsite location.

2011-10-28_18:23:38 --- Total backup time: 0 hour(s) 38 minute(s) 28 second(s)

2011-10-28_18:23:39 - Offline RSync backup completed.

2011-10-28_18:23:39 - Offline RSync backup exit code: 0




To test the online script, make sure you are root and type the following commands:



nohup ./rsync-online.sh &

tail -f /var/temp/rsync-online*.log



The command above will start the script in the background and will allow it to run even if you log off the system.
The tail command will display the last 10 lines of the log. The -f option will keep the command active and continuously show the end of the log...thus you can sit there and just watch the entries show up in the log as they are written (works with any log file). Also note that this is the temporary log file which everything is placed until the very end...which is then copied to the main log file shared between both online and offline scripts.
Press CTRL+C to stop watching the log file.
Reference: OSE Backup Procedures (multiple)
NOTE: Synchronize files with rsync
4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

Backup - Individual Mailbox
The 2nd method involves backing up individual mailboxes. This process can occur while the server is online and thus will not cause any downtime. It can be run as often as you want but you should consider the performance impact on the server as well as how long each run will take. I plan to schedule it once per day during non-peak hours.
mailbox-backup.sh



#!/bin/bash

#############################################

## Name : mailbox-backup.sh

## Version : 1.1

## Date : 2012-01-09

## Author : LHammonds

## Purpose : Backup individual mailbox accounts.

## Compatibility : Verified on Ubuntu Server 10.04.3 - 10.04.4 LTS, Zimbra 7.1.2 - 7.2.0 OSE

## Requirements : Zimbra must be online, must be run as root user.

## Run Frequency : Once or more per day.

## Exit Codes : (if multiple errors, value is the addition of codes)

## 0 = Success (or non-critical failure)

## 1 = Root access failure

## 2 = Archive creation failure

## 4 = Archive purge error

## 8 = configuration error

## 16 = Offsite mount failure

## 32 = Offsite copy failure

################ CHANGE LOG #################

## DATE WHO WHAT WAS CHANGED

## ---------- --- ----------------------------

## 2011-10-23 LTH Created script.

## 2011-11-05 LTH Move common variables and functions to external file.

## 2011-11-06 LTH Additional error checks and better log info.

## 2012-01-09 LTH Bugfix f_PurgeOldestArchive

#############################################
## Import common variables and functions.

source /var/scripts/common/standard.conf
## Define local variables.

LOGFILE="${TEMPDIR}/mailbox-backup.log"

HISTORYFILE="${TEMPDIR}/mailbox-backup-size-history.log"

TARGETDIR="${BACKUPDIR}/mailbox"

OFFSITEBACKDIR="${OFFSITEDIR}/mailbox"

ARCHIVEFILE="`date +%Y-%m-%d-%H-%M`_mailbox-all.tar"

LOCKFILE="${TEMPDIR}/mailbox-backup.lock"

EXCEPTIONS="spam.ppnvqogp0@${MYDOMAIN};ham.iki6sotcy@${MYDOMAIN};virus-quarantine.qvj6nc_jl@${MYDOMAIN}"

RETURNVALUE=0

UCOUNT=0

ERRORFLAG=0
#######################################

## FUNCTIONS ##

#######################################
function f_PurgeOldestArchive()

{

## Purpose: Delete the oldest archive on the remote site.

## Return values:

## 0 = Success

## 1 = Cannot delete file

## 9 = Configuration error, path empty
## Variable Error Check. *

if [ ${OFFSITEBACKDIR} = "" ]; then

## Make darn sure the path is not empty since we do NOT

## want to start purging files from a random location.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Purge error: OFFSITEBACKDIR site variable is empty!" >> ${LOGFILE}

return 9

fi

## Get the name of the oldest file.

OLDESTFILE=`ls -1t ${OFFSITEBACKDIR} | tail -1`

FILESIZE=`ls -la ${OFFSITEDIR}/${OLDFILE} | awk '{print $5}' | sed -e :a -e 's/(.*[0-9])([0-9]{3})/1,2/;ta'`

if [ "${OLDESTFILE}" = "" ]; then

## Error. Filename variable empty.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Purge error: OLDESTFILE variable is empty." >> ${LOGFILE}

return 9

else

FILESIZE=`ls -lak "${OFFSITEBACKDIR}/${OLDESTFILE}" | awk '{ print $5 }' | sed -e :a -e 's/(.*[0-9])([0-9]{3})/1,2/;ta'`

echo "`date +%Y-%m-%d_%H:%M:%S` --- Purging old file: ${OFFSITEBACKDIR}/${OLDESTFILE}, Size = ${FILESIZE} kb" >> ${LOGFILE}

rm "${OFFSITEBACKDIR}/${OLDESTFILE}"

if [ -f "${OFFSITEBACKDIR}/${OLDESTFILE}" ]; then

## File still exists. Return error.

return 1

else

return 0

fi

fi

}
function f_cleanup()

{

if [ -f "${LOCKFILE}" ]; then

## Remove run file since this script is complete.

rm ${LOCKFILE}

fi

}
function f_emergencyexit()

{

## Purpose: Exit script as cleanly as possible.

## Parameter #1 = Error Code.

f_cleanup

f_sendmail "Zimbra Mailbox Backup Error" "EXIT CODE = ${1}"

echo "`date +%Y-%m-%d_%H:%M:%S` - Mailbox backup aborted. EXIT CODE: ${1}" >> ${LOGFILE}

## Write script name and error code to the system log.

logger "${SCRIPTNAME}: ERROR CODE = ${1}"

exit $1

}
#######################################

## MAIN PROGRAM ##

#######################################
## Requirement Check: Script must run as root user.

if [ "$(id -u)" != "0" ]; then

## FATAL ERROR DETECTED: Document problem and terminate script.

ERRORFLAG=$((${ERRORFLAG} + 1))

echo "`date +%Y-%m-%d_%H:%M:%S` - Mailbox backup aborted. ERROR CODE ${ERRORFLAG}: Script must be run as root user instead of $(whoami)." | tee -a ${LOGFILE}

f_emergencyexit ${ERRORFLAG}

fi
if [ -f "${LOCKFILE}" ]; then

## Last call to this script is still running or failed to remove its lock file.

## As an additional check, see if the file is older than today...if so, we should

## probably send an email notification of a problem that may need manual interention.

FILEDATE=$(stat -c %y ${LOCKFILE})

FILEDATE=${FILEDATE%% *}

if [ "${FILEDATE}" != "$(date +%Y-%m-%d)" ]; then

## Lock file not created today, might need to be manually deleted. Send email notification.

f_sendmail "Zimbra Mailbox Backup Warning" "Warning: This script cannot run if it detects this lock file: ${LOCKFILE}

This file should only exist while this script is running which should not take more than a day.

System Date: $(date +%Y-%m-%d)
Lock File Date: ${FILEDATE}

If you determine that the file should be removed, do so by typing this command on the server's console: rm ${LOCKFILE}"

fi

exit 0

else

## Create the "script is running" lock file and process the script.

echo "`date +%Y-%m-%d_%H:%M:%S` - ${HOSTNAME}:${SCRIPTNAME} is currently running." > ${LOCKFILE}

fi
## Record the start time of the backup process.

STARTTIME="$(date +%s)"
echo "`date +%Y-%m-%d_%H:%M:%S` - Individual mailbox backup started." >> ${LOGFILE}

if [ -d "${TARGETDIR}" ]; then

## Purge existing archives.

rm ${TARGETDIR}/*.tgz 1>/dev/null 2>&1

else

## Make the folder since it does not exist.

mkdir -p ${TARGETDIR} 1>/dev/null 2>&1

fi

for ACCT in `su - zimbra -c "zmprov -l gaa"`

do

## Check to see if current account should be skipped.

if echo "${EXCEPTIONS}" | grep -q ${ACCT}

then

## Exception found, skip this account.

echo "" > /dev/null

else

## Backup user account.

UCOUNT=$((UCOUNT+1))

${ZIMBRADIR}/bin/zmmailbox -z -m ${ACCT} getRestURL "//?fmt=tgz" > ${TARGETDIR}/${ACCT}.tgz

RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## Something went wrong.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Error on ${ACCT}, RETURN VALUE = ${RETURNVALUE}" >> ${LOGFILE}

ERRORFLAG=$((ERRORFLAG+1))

else

## Calculate archive size.

MAILBOXSIZE=$(stat -c %s ${TARGETDIR}/${ACCT}.tgz)

## Comment out the below line if you do not want details in the log file.

echo "`date +%Y-%m-%d_%H:%M:%S` --- ${ACCT}, ${MAILBOXSIZE} bytes" >> ${LOGFILE}

fi

fi

done

echo "`date +%Y-%m-%d_%H:%M:%S` --- ${UCOUNT} accounts processed." >> ${LOGFILE}
## Calculate mailbox backup time.

FINISHTIME="$(date +%s)"

ELAPSEDTIME="$(expr ${FINISHTIME} - ${STARTTIME})"

HOURS=$((${ELAPSEDTIME} / 3600))

ELAPSEDTIME=$((${ELAPSEDTIME} - ${HOURS} * 3600))

MINUTES=$((${ELAPSEDTIME} / 60))

SECONDS=$((${ELAPSEDTIME} - ${MINUTES} * 60))
echo "`date +%Y-%m-%d_%H:%M:%S` --- Backup time for ${UCOUNT} mailboxes: ${HOURS} hour(s) ${MINUTES} minute(s) ${SECONDS} second(s)" >> ${LOGFILE}
echo "`date +%Y-%m-%d_%H:%M:%S` --- Setting file permissions on ${TARGETDIR}/*.tgz" >> ${LOGFILE}

chmod 0600 ${TARGETDIR}/*.tgz

echo "`date +%Y-%m-%d_%H:%M:%S` --- Creating a single file for archiving: ${TEMPDIR}/${ARCHIVEFILE}" >> ${LOGFILE}

tar -cf ${TEMPDIR}/${ARCHIVEFILE} ${TARGETDIR} 1>/dev/null 2>&1

RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## Something went wrong.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Error creating ${TEMPDIR}/${ARCHIVEFILE}, Return Value: ${RETURNVALUE}" >> ${LOGFILE}

ERRORFLAG=$((ERRORFLAG+2))

fi

ARCHIVESIZE=$(stat -c %s ${TEMPDIR}/${ARCHIVEFILE})

if [ ! -f "${HISTORYFILE}" ]; then

## Create history log and include header description as 1st line, field separator = space character.

echo "Date Archive SizeInBytes" > ${HISTORYFILE}

fi

## Append archive size to the history log.

echo "`date +%Y-%m-%d` ${ARCHIVEFILE} ${ARCHIVESIZE}" >> ${HISTORYFILE}
## Mount the offsite Windows share folder.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Mounting ${OFFSITEDIR}" >> ${LOGFILE}

f_mount

if [ -f ${OFFSITETESTFILE} ]; then

## Remote site is online / available.

if [ ! -d ${OFFSITEBACKDIR} ]; then

## Make the backup folder since it does not exist yet.

mkdir -p ${OFFSITEBACKDIR}

fi

if [ -f ${TEMPDIR}/${ARCHIVEFILE} ]; then

## Make sure space is available on the remote server to copy the file.

FREESPACE=`df -k ${OFFSITEDIR} | grep ${OFFSITEDIR} | awk '{ print $3 }'`

BACKUPSIZE=`ls -lak "${TEMPDIR}/${ARCHIVEFILE}" | awk '{ print $5 }'`

if [ ${FREESPACE} -lt ${BACKUPSIZE} ]; then

## Not enough free space available. Purge existing backups until there is room.

ENOUGHSPACE=0

while [ ${ENOUGHSPACE} -eq 0 ]

do

f_PurgeOldestArchive

RETURNVALUE=$?

case ${RETURNVALUE} in

1)

## Cannot purge archives to free up space. End program gracefully.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Not enough free space on ${OFFSITEBACKDIR} and cannot purge old archives. Script aborted." >> ${TEMPLOG}

## Stop and exit the script with an error code.

ERRORFLAG=$((${ERRORFLAG} + 4))

f_emergencyexit ${ERRORFLAG}

;;

9)

## Configuration error, end program gracefully.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Configuration problem. Script aborted." >> ${TEMPLOG}

## Stop and exit the script with an error code.

ERRORFLAG=$((${ERRORFLAG} + 8))

f_emergencyexit ${ERRORFLAG}

;;

esac

FREESPACE=`df -k ${OFFSITEDIR} | grep ${OFFSITEDIR} | awk '{ print $3 }'`

if [ ${FREESPACE} -gt ${BACKUPSIZE} ]; then

## Enough space is now available.

ENOUGHSPACE=1

else

## Not enough space is available yet.

ENOUGHSPACE=0

fi

done

fi
echo "`date +%Y-%m-%d_%H:%M:%S` --- Copying ${TEMPDIR}/${ARCHIVEFILE} to ${OFFSITEBACKDIR}/" >> ${LOGFILE}

cp ${TEMPDIR}/${ARCHIVEFILE} ${OFFSITEBACKDIR}/${ARCHIVEFILE} 1>/dev/null 2>&1

fi

else

## Remote site is offline / unavailable.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Error: Remote site is unavailable: ${OFFSITEBACKDIR}" >> ${LOGFILE}

ERRORFLAG=$((ERRORFLAG+16))

fi
if [ -f ${OFFSITEBACKDIR}/${ARCHIVEFILE} ]; then

## Remote copy worked. Remove local archive.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Copied ${ARCHIVESIZE} bytes." >> ${LOGFILE}

echo "`date +%Y-%m-%d_%H:%M:%S` --- Removing ${TEMPDIR}/${ARCHIVEFILE}" >> ${LOGFILE}

rm ${TEMPDIR}/${ARCHIVEFILE}
FREESPACE=`df -k ${OFFSITEDIR} | grep ${OFFSITEDIR} | awk '{ print $3 }'`

## Comment out the below line if you do not want to receive statistic emails.

f_sendmail "Zimbra Individual Mailbox Backup" "${UCOUNT} accounts backed up.

Total archive size: $((${ARCHIVESIZE}/1024)) kb

Available Backup Space: ${FREESPACE} kb"
## Uncomment the following 2 lines if you do not wish to have a local copy of individual mailboxes.

# rm ${TARGETDIR}/*.tgz

# rmdir ${TARGETDIR}

else

## Remote copy failed.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Error copying to ${OFFSITEBACKDIR}/${ARCHIVEFILE}" >> ${LOGFILE}

ERRORFLAG=$((ERRORFLAG+32))

fi
## Calculate total time for backup.

FINISHTIME="$(date +%s)"

ELAPSEDTIME="$(expr ${FINISHTIME} - ${STARTTIME})"

HOURS=$((${ELAPSEDTIME} / 3600))

ELAPSEDTIME=$((${ELAPSEDTIME} - ${HOURS} * 3600))

MINUTES=$((${ELAPSEDTIME} / 60))

SECONDS=$((${ELAPSEDTIME} - ${MINUTES} * 60))
echo "`date +%Y-%m-%d_%H:%M:%S` --- Total backup time: ${HOURS} hour(s) ${MINUTES} minute(s) ${SECONDS} second(s)" >> ${LOGFILE}
if [ ${ERRORFLAG} -ne 0 ]; then

f_sendmail "Zimbra Individual Mailbox Backup Error" "${ERRORFLAG} errors detected while trying to backup ${UCOUNT} individual mailboxes."

fi

## Unmount the offsite backup location.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Dismounting ${OFFSITEDIR}" >> ${LOGFILE}

f_umount

## Perform cleanup routine.

f_cleanup

## Exit with the combined return code value.

echo "`date +%Y-%m-%d_%H:%M:%S` - Individual mailbox backup complete. Exit code: ${ERRORFLAG}" >> ${LOGFILE}

exit ${ERRORFLAG}




Sample output of mailbox-backup.log



2011-11-06_15:48:02 - Individual mailbox backup started.

2011-11-06_15:48:11 --- admin@mydomain.com, 6781 bytes

2011-11-06_15:48:13 --- lhammonds@mydomain.com, 1066 bytes

2011-11-06_15:48:16 --- jsmith@mydomain.com, 1067 bytes

2011-11-06_15:48:18 --- jdoe@mydomain.com, 1066 bytes

2011-11-06_15:48:21 --- administrator@mydomain.com, 1069 bytes

2011-11-06_15:48:23 --- foobar@mydomain.com, 1067 bytes

2011-11-06_15:48:25 --- jvorhees@mydomain.com, 1068 bytes

2011-11-06_15:48:28 --- conferencerooms@mydomain.com, 1067 bytes

2011-11-06_15:48:30 --- test@mydomain.com, 1068 bytes

2011-11-06_15:48:48 --- 9 accounts processed.

2011-11-06_15:48:48 --- Backup time for 9 mailboxes: 0 hour(s) 0 minute(s) 46 second(s)

2011-11-06_15:48:48 --- Setting file permissions on /var/backup/mailbox/*.tgz

2011-11-06_15:48:48 --- Creating a single file for archiving: /var/temp/2011-11-06-15-48_mailbox-all.tar

2011-11-06_15:48:48 --- Mounting /mnt/backup

2011-11-06_15:48:49 --- Copying /var/temp/2011-11-06-15-48_mailbox-all.tar to /mnt/backup/mailbox/

2011-11-06_15:48:49 --- Copied 61440 bytes.

2011-11-06_15:48:49 --- Removing /var/temp/2011-11-06-15-48_mailbox-all.tar

2011-11-06_15:48:49 --- Total backup time: 0 hour(s) 0 minute(s) 47 second(s)

2011-11-06_15:48:49 --- Dismounting /mnt/backup

2011-11-06_15:48:49 - Individual mailbox backup complete. Exit code: 0


Sample output of mailbox-backup-size-history.log



Date Archive SizeInBytes

2011-11-06 2011-11-06-11-21_mailbox-all.tar 61440

2011-11-06 2011-11-06-15-17_mailbox-all.tar 61440

2011-11-06 2011-11-06-15-21_mailbox-all.tar 61440

2011-11-06 2011-11-06-15-22_mailbox-all.tar 61440

2011-11-06 2011-11-06-15-32_mailbox-all.tar 61440

2011-11-06 2011-11-06-15-48_mailbox-all.tar 61440


Sample email notification



Subject: Zimbra Individual Mailbox Backup
9 accounts backed up.
Total archive size: 60 kb
Available Backup Space: 28440616 kb
Server: mail

Program: /var/scripts/prod/mailbox-backup.sh

Log: /var/temp/mailbox-backup.log


Sample error email notification



Subject: Zimbra Individual Mailbox Backup Error
1 errors detected while trying to backup 9 individual mailboxes.
Server: mail

Program: /var/scripts/prod/mailbox-backup.sh

Log: /var/temp/mailbox-backup.log


Sample /var/log/messages



Nov 6 11:13:01 mail administrator: /var/scripts/prod/mailbox-backup.sh: ERROR CODE = 1

Nov 6 11:15:02 mail root: /var/scripts/prod/mailbox-backup.sh: ERROR CODE = 2

Nov 6 11:18:03 mail root: /var/scripts/prod/mailbox-backup.sh: ERROR CODE = 4

Nov 6 11:23:04 mail root: /var/scripts/prod/mailbox-backup.sh: ERROR CODE = 8

Nov 6 11:33:05 mail root: /var/scripts/prod/mailbox-backup.sh: ERROR CODE = 16

Nov 6 11:43:06 mail root: /var/scripts/prod/mailbox-backup.sh: ERROR CODE = 32

4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

ZIMBRA RESTORE
I SEE THE NEED TO RESTORE FROM AT LEAST SEVERAL DIFFERENT SCENARIOS. THAT MEANS COMING UP WITH A RESTORE PLAN AND SCRIPTS TO HELP SPEED UP RESTORE TIME AND REDUCE ERRORS DURING EMERGENCY SCENARIOS. THIS ALSO MEANS TESTING EACH OF THESE RESTORE PLANS; OTHERWISE YOU ARE PLAYING RUSSIAN ROULETTE WITH MORE THAN ONE BULLET IN THE REVOLVER! ALWAYS REMEMBER THAT THE VAST MAJORITY OF ADMINISTRATORS INVOLUNTARILY REMOVED FROM THEIR JOB ARE TYPICALLY RELATED TO DATA LOSS THAT CANNOT BE RECOVERED.
HERE ARE THE SCENARIOS I AM GOING TO COVER AND TEST:




RESTORE INDIVIDUAL MAILBOX FROM A LOCAL COPY - WE WILL RESTORE A MAILBOX ACCOUNT USING THE LATEST INDIVIDUAL MAILBOX BACKUP WHICH IS STORED ON THE LOCAL SERVER. THIS CAN BE DONE AT ANY TIME AND WILL NOT IMPACT SERVER UPTIME.

RESTORE INDIVIDUAL MAILBOX FROM AN OFFSITE LOCATION - WE WILL RESTORE A MAILBOX ACCOUNT USING ONE OF THE ARCHIVES LOCATED ON THE OFFSITE STORAGE. THIS CAN BE DONE AT ANY TIME AND WILL NOT IMPACT SERVER UPTIME.

RESTORE EXISTING SERVER FROM A LOCAL COPY (FASTEST, BUT POTENTIALLY PROBLEMATIC) - WE WILL USE THE LOCAL FOLDER USED FOR DOING DAILY RSYNC BACKUPS. THE CAVEAT HERE IS THAT YOU ONLY WANT TO DO THIS IF THE LAST RSYNC WAS FROM THE OFFLINE RSYNC SCRIPT...MEANING IT IS A COMPLETE SNAPSHOT AND NOT FROM ANY OF THE ONLINE RSYNCS WHICH DID NOT COPY OPEN AND IN-USE FILES. THIS WILL CAUSE THE SERVER TO BE OFFLINE, SO BE SURE TO COORDINATE AND PLAN ACCORDINGLY.

RESTORE EXISTING SERVER FROM AN OFFSITE LOCATION (SLOWER, BUT MORE RELIABLE) - WE WILL RESTORE THE SERVER USING ONE OF THE ARCHIVES LOCATED ON THE OFFSITE STORAGE. THIS WILL CAUSE THE SERVER TO BE OFFLINE, SO BE SURE TO COORDINATE AND PLAN ACCORDINGLY.

RESTORE TO NEW SERVER (PRODUCTION SERVER UNAVAILABLE) - WE WILL ASSUME THE PRODUCTION SERVER IS OFFLINE AND INACCESSIBLE. WE WILL CONFIGURE A NEW SERVER AND RESTORE USING ONE OF THE ARCHIVES LOCATED ON THE OFFSITE STORAGE.

4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

SCENARIO #1 RESTORE INDIVIDUAL MAILBOX FROM A LOCAL COPY
THIS PROCESS WILL ASSUME YOU ARE WANTING TO RESTORE A MAILBOX BACK TO THE WAY IT WAS WHEN LAST BACKED UP. THIS MEANS ANYTHING NEW SINCE THE BACKUP WILL BE WIPED OUT. IF THIS IS NOT DESIRED, A SIMPLE SOLUTION (WHICH WILL BE MY STANDARD PROTOCOL) WILL BE TO CREATE A NEW MAILBOX AND RESTORE TO IT.
IF CREATING A NEW MAILBOX, BE SURE TO SET A PASSWORD ON IT AND TEST IT BY LOGGING INTO THE ACCOUNT...THIS ALSO CREATES THE MAILBOX STORE WHEN ACCESSED THE 1ST TIME. THEN COPY THE USER'S MAILBOX ARCHIVE TO LOOK LIKE THE ARCHIVE FOR THE RESTORE ACCOUNT.
EXAMPLE #1 - RESTORE THE ADMIN MAILBOX.


/VAR/SCRIPTS/PROD/MAILBOX-RESTORE-LOCAL.SH ADMIN@MYDOMAIN.COM


ONSCREEN RESULT:



2011-11-06_17:45:55 - RESTORED MAILBOX --> ADMIN@MYDOMAIN.COM


RECORDED EVENT IN THE LOG: /VAR/TEMP/MAILBOX-RESTORE.LOG



2011-11-06_17:45:55 - RESTORED MAILBOX --> ADMIN@MYDOMAIN.COM


EXAMPLE #2 - RESTORE THE ADMIN MAILBOX TO A TEMPORARY ACCOUNT CALLED "RESTORE".


LOGIN TO THE ADMIN CONSOLE: H T T P S ://MAIL.MYDOMAIN.COM:7071

CREATE A NEW ACCOUNT CALLED RESTORE AND SET THE PASSWORD

LOGIN TO THE WEBMAIL USING THE RESTORE ACCOUNT: H T T P S ://MAIL.MYDOMAIN.COM

ONCE LOGGED IN TO VERIFY THE EMPTY ACCOUNT WORKS, LOGOUT

ACCESS THE UBUNTU SERVER. AT THE LOGIN PROMPT, LOGIN WITH YOUR ADMINISTRATOR ACCOUNT (ADMINISTRATOR / MYADMINPASS) AND THEN TYPE SU AND THE ROOT PASSWORD (MYROOTPASS)

TYPE THE FOLLOWING:



CP /VAR/BACKUP/MAILBOX/ADMIN@MYDOMAIN.COM.TGZ /VAR/BACKUP/MAILBOX/RESTORE@MYDOMAIN.COM.TGZ

/VAR/SCRIPTS/PROD/MAILBOX-RESTORE-LOCAL.SH RESTORE@MYDOMAIN.COM






MAILBOX-RESTORE-LOCAL.SH



#!/BIN/BASH

#############################################

## NAME : MAILBOX-RESTORE-LOCAL.SH

## VERSION : 1.0

## DATE : 2011-11-06

## AUTHOR : LHAMMONDS

## COMPATIBILITY : VERIFIED ON UBUNTU 10.04.3 - 10.04.4 LTS, ZIMBRA 7.1.2 - 7.2.0

## PURPOSE : RESTORE INDIVIDUAL MAILBOX ACCOUNTS.

## RUN FREQUENCY : MANUAL AS NEEDED.

## EXIT CODES : (IF MULTIPLE ERRORS, VALUE IS THE ADDITION OF CODES)

## 0 = SUCCESS

## 1 = PARAMETER FAILURE

## 2 = UNKNOWN MAILBOX ACCOUNT

## 4 = MISSING ARCHIVE FOLDER

## 8 = MISSING ARCHIVE FILE

## 16 = MAILBOX RESTORE FAILURE

################ CHANGE LOG #################

## DATE WHO WHAT WAS CHANGED

## ---------- --- ----------------------------

## 2011-10-24 LTH CREATED SCRIPT.

## 2011-11-06 LTH MOVE COMMON VARIABLES AND FUNCTIONS TO EXTERNAL FILE.

#############################################
## IMPORT COMMON VARIABLES AND FUNCTIONS.

SOURCE /VAR/SCRIPTS/COMMON/STANDARD.CONF
## DEFINE LOCAL VARIABLES.

LOGFILE="${TEMPDIR}/MAILBOX-RESTORE.LOG"

ARCHIVEDIR="${BACKUPDIR}/MAILBOX"

ACCT=$1

RETURNVALUE=0
#######################################

## FUNCTIONS ##

#######################################
FUNCTION F_SHOWHELP()

{

ECHO ""

ECHO "USAGE : ${SCRIPTNAME} USER@${MYDOMAIN}"

ECHO ""

ECHO "NOTE: YOU COULD CREATE A TEMPORARY ACCOUNT AND COPY THE DESIRED ARCHIVE"

ECHO " TO BE NAMED THE SAME AS THE TEMPORARY ACCOUNT IN ORDER TO RESTORE"

ECHO " TO A NEW MAILBOX AND PRESERVE THE EXISTING MAILBOX."

ECHO " EXAMPLE:"

ECHO " CD ${ARCHIVEDIR}"

ECHO " CP ADMIN@${MYDOMAIN}.TGZ RESTORE@${MYDOMAIN}.TGZ"

ECHO " ${SCRIPTNAME} RESTORE@${MYDOMAIN}"

ECHO ""

}
FUNCTION F_EMERGENCYEXIT()

{

## PURPOSE: EXIT SCRIPT AS CLEANLY AS POSSIBLE.

## PARAMETER #1 = ERROR CODE.

ECHO -E "INDIVIDUAL MAILBOX RESTORE ABORTED. EXIT CODE: ${1}N"

EXIT $1

}
#######################################

## MAIN PROGRAM ##

#######################################
## CHECK COMMAND-LINE PARAMETERS.

CASE "$1" IN

"")

F_SHOWHELP

F_EMERGENCYEXIT 1

;;

--HELP|-H|-?)

F_SHOWHELP

F_EMERGENCYEXIT 1

;;

*)

ACCT=$1

;;

ESAC
## CHECK TO MAKE SURE THE ARCHIVE FOLDER EXISTS.

IF [ ! -D "${ARCHIVEDIR}" ]; THEN

## ERROR: ARCHIVE FOLDER DOES NOT EXIST.

ECHO "ERROR: THE ARCHIVE FOLDER DOES NOT EXIST! ${ARCHIVEDIR}"

F_EMERGENCYEXIT 4

FI
## CHECK TO MAKE SURE THE ARCHIVE EXISTS.

IF [ ! -F "${ARCHIVEDIR}/${ACCT}.TGZ" ]; THEN

## ERROR: ARCHIVE DOES NOT EXIST.

ECHO "ERROR: THE ARCHIVE DOES NOT EXIST! ${ARCHIVEDIR}/${ACCT}.TGZ"

F_EMERGENCYEXIT 8

FI
## CHECK TO MAKE SURE PARAMETER IS A VALID MAILBOX ACCOUNT NAME.

IF `SU - ZIMBRA -C "ZMPROV -L GAA" | GREP -Q ${ACCT}`

THEN

## THE PARAMETER CONTAINS A VALID MAILBOX ACCOUNT.

ECHO "" > /DEV/NULL

ELSE

## INVALID MAILBOX ACCOUNT.

ECHO "ERROR: INVALID MAILBOX: ${ACCT}"

F_SHOWHELP

F_EMERGENCYEXIT 2

FI
${ZIMBRADIR}/BIN/ZMMAILBOX -Z -M ${ACCT} POSTRESTURL "//?FMT=TGZ&RESOLVE=RESET" ${ARCHIVEDIR}/${ACCT}.TGZ

RETURNVALUE=$?

IF [ ${RETURNVALUE} -NE 0 ]; THEN

## SOMETHING WENT WRONG.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - ERROR RESTORING ${ACCT}, RETURN VALUE = ${RETURNVALUE}" | TEE -A ${LOGFILE}

F_EMERGENCYEXIT 16

FI

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - RESTORED MAILBOX --> ${ACCT}" | TEE -A ${LOGFILE}

F_SENDMAIL "ZIMBRA USER MAILBOX RESTORE" "${ACCT} WAS MANUALLY RESTORED."
EXIT 0


IF YOU DO NOT SUPPLY AN ACCOUNT TO THE SCRIPT AS A PARAMETER, IT WILL DISPLAY THE FOLLOWING HELP TEXT:



/VAR/SCRIPTS/PROD/MAILBOX-RESTORE.SH
USAGE : ./MAILBOX-RESTORE-LOCAL.SH USER@MYDOMAIN.COM
NOTE: YOU COULD CREATE A TEMPORARY ACCOUNT AND COPY THE DESIRED ARCHIVE

TO BE NAMED THE SAME AS THE TEMPORARY ACCOUNT IN ORDER TO RESTORE

TO A NEW MAILBOX AND PRESERVE THE EXISTING MAILBOX.

EXAMPLE:

CD /VAR/BACKUP/MAILBOX

CP ADMIN@MYDOMAIN.COM.TGZ RESTORE@MYDOMAIN.COM.TGZ

/VAR/SCRIPTS/PROD/MAILBOX-RESTORE.SH RESTORE@MYDOMAIN.COM
INDIVIDUAL MAILBOX RESTORE ABORTED. EXIT CODE: 1



NOTE: THE ABOVE WILL ACTUALLY USE YOUR DOMAIN IN ALL EXAMPLES BECAUSE IT PULLS THE DOMAIN FROM THE STANDARD.CONF FILE.
4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

Scenario #2 Restore individual mailbox from an offsite location
Here is the general outline of the script:
Parameter #1 (required) = Account in which we will find the archive for.

Parameter #2 (optional) = Account in which we will restore the selected archive into (default = parameter 1)
Step 1 - Display all offsite archives (order oldest to newest) and present list to user for selection

Step 2 - Extract only the account's file from the archive to the temp folder

Step 3 - Restore archive to desired account
----------------------
/var/scripts/prod/mailbox-restore.sh



#!/bin/bash

#############################################

## Name : mailbox-restore.sh

## Version : 1.0

## Date : 2011-11-08

## Author : LHammonds

## Compatibility : Verified on Ubuntu 10.04.3 - 10.04.4 LTS, Zimbra 7.1.3 - 7.2.0 OSE

## Purpose : Restore individual mailbox accounts.

## Run Frequency : Manual as needed.

## Parameters :

## 1 = (Required) Account to search for archive (e.g. jdoe@mydomain.com)

## 2 = (Optional) Account to restore archive to (e.g. restore@mydomain.com)

## Exit Codes :

## 0 = Success or non-critical problem

## 1 = Archive folder does not exist

## 2 = Invalid mailbox account

## 3 = Mailbox restore failure

################ CHANGE LOG #################

## DATE WHO WHAT WAS CHANGED

## ---------- --- ----------------------------

## 2011-11-08 LTH Created script.

#############################################
## Import common variables and functions.

source /var/scripts/common/standard.conf
## Define local variables.

LOGFILE="${TEMPDIR}/mailbox-restore.log"

ARCHIVEDIR="${OFFSITEDIR}/mailbox"

ACCT1=$1

ACCT2=$2

RETURNVALUE=0
#######################################

## FUNCTIONS ##

#######################################
function f_showhelp()

{

echo ""

echo "Usage : ${SCRIPTNAME} user@${MYDOMAIN} restore@${MYDOMAIN} (optional)"

echo ""

echo "NOTE: If you specify a 2nd account, the 1st account data will be"

echo " restored to the 2nd account."

echo ""

}
function f_emergencyexit()

{

## Purpose: Exit script as cleanly as possible.

## Parameter #1 = Error Code.
if [ -f ${REMOTEDIR}/online.txt ]; then

## Dismount the remote site.

f_umount

fi

echo -e "Individual mailbox restore aborted. EXIT CODE: ${1}
"

exit $1

}
#######################################

## MAIN PROGRAM ##

#######################################
## Check command-line parameters.

case "$1" in

"")

f_showhelp

exit 0

;;

--help|-h|-?)

f_showhelp

exit 0

;;

*)

ACCT1=$1

ACCT2=$2

;;

esac
if [ "${ACCT1}" = "" ]; then

## Required parameter not specified.

f_showhelp

exit 0

fi
if [ "${ACCT2}" = "" ]; then

## Restore to the same account.

ACCT2=${ACCT1}

fi
## Mount the remote site.

f_mount
## Check to make sure the archive folder exists.

if [ ! -d "${ARCHIVEDIR}" ]; then

## ERROR: Archive folder does not exist.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: The archive folder does not exist! ${ARCHIVEDIR}, EC=1" | tee -a ${LOGFILE}

f_emergencyexit 1

fi
## Define user prompt using the special PS3 variable.

PS3="Type number for the desired archive or 'q' to quit: "
## Get sorted list of all archives (newest at the bottom).

FILELIST=$(find ${ARCHIVEDIR}/*.tar -maxdepth 1 -type f | sort -f)
## Prompt user to select a file to use.

## NOTE: If it is a long list, user can scroll up if

## using PuTTY to see older files.

select GETFILE in ${FILELIST}; do

if [ "${GETFILE}" != "" ]; then

FILENAME=${GETFILE}

fi

break

done
if [ "${FILENAME}" = "" ]; then

## User opted to quit.

echo -e "Exiting restore program.
"

exit 0

fi
## Extract just the mailbox file from the archive.

tar --extract -C ${TEMPDIR} --file=${FILENAME} --wildcards "*${ACCT1}*" --no-anchored --strip-components=3
if [ ! -f ${TEMPDIR}/${ACCT1}.tgz ]; then

## File did not exist in the archive.

echo -e "No file found matching ${ACCT1}
"

exit 0

fi
## Check to make sure parameter is a valid mailbox account name.

if `su - zimbra -c "zmprov -l gaa" | grep -q ${ACCT2}`

then

## The parameter contains a valid mailbox account.

echo "" > /dev/null

else

## Invalid mailbox account.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Invalid mailbox: ${ACCT2}, EC=2" | tee -a ${LOGFILE}

f_showhelp

f_emergencyexit 2

fi
${ZIMBRADIR}/bin/zmmailbox -z -m ${ACCT2} postRestURL "//?fmt=tgz&resolve=reset" ${TEMPDIR}/${ACCT1}.tgz

RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## Something went wrong.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Restore failure on ${ACCT2}, RETURN VALUE=${RETURNVALUE}, EC=3" | tee -a ${LOGFILE}

f_emergencyexit 3

fi

echo "`date +%Y-%m-%d_%H:%M:%S` - Restored mailbox --> ${ACCT2}" | tee -a ${LOGFILE}

f_sendmail "Zimbra User Mailbox Restore" "${ACCT2} was manually restored from ${ACCT1}"
## Clean up temporary files.

if [ -f ${TEMPDIR}/${ACCT1}.tgz ]; then

rm ${TEMPDIR}/${ACCT1}.tgz

fi
## Dismount the remote site.

f_umount

exit 0


/var/temp/mailbox-restore.log (sample)



2011-11-08_13:01:39 - ERROR: The archive folder does not exist! /mnt/backup/configtypo, EC=1

2011-11-08_15:54:34 - ERROR: Restore failure for admin@mydomain.com, RETURN VALUE=2, EC=3

2011-11-08_15:55:47 - Restored mailbox --> admin@mydomain.com

2011-11-08_15:57:50 - Restored mailbox --> lhammonds@mydomain.com

2011-11-08_16:00:14 - Restored mailbox --> ddiggler@mydomain.com

2011-11-08_16:01:16 - Restored mailbox --> restore@mydomain.com

2011-11-08_16:28:38 - ERROR: Invalid mailbox: bogus@mydomain.com, EC=2

4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

SCENARIO #3 RESTORE EXISTING SERVER FROM A LOCAL COPY
WE WILL USE THE LOCAL FOLDER USED FOR DOING DAILY RSYNC BACKUPS.
THE CAVEOT HERE IS THAT YOU ONLY WANT TO DO THIS IF THE LAST RSYNC WAS FROM THE OFFLINE RSYNC SCRIPT...MEANING IT IS A COMPLETE SNAPSHOT AND NOT FROM ANY OF THE ONLINE RSYNCS WHICH DID NOT COPY OPEN AND IN-USE FILES. IF THE LAST RSYNC WAS THE ONLINE VERSION, WE WILL NEED TO USE A DIFFERENT SCRIPT TO ACCESS REMOTE STORAGE.
THIS SCRIPT IS INTENDED TO BE RUN MANUALLY AS THE ROOT USER.
HERE ARE THE INSTRUCTIONS TO RESTORE THE CURRENTLY RUNNING SERVER USING THE SCRIPT BELOW:




BEFORE RUNNING THIS, MAKE SURE EVERYONE IS AWARE THAT ZIMBRA WILL BE GOING DOWN TO BE RESTORED.

AT THE LOGIN PROMPT, LOGIN WITH YOUR ADMINISTRATOR ACCOUNT (ADMINISTRATOR / MYADMINPASS) AND THEN TYPE SU AND THE ROOT PASSWORD (MYROOTPASS)

RUN THE SCRIPT BY TYPING /VAR/SCRIPTS/PROD/RESTORE-RSYNC-LOCAL.SH

IF YOU MISSED ANY OF THE OUTPUT ON THE SCREEN, YOU CAN VIEW THE LOG BY TYPING VI /VAR/TEMP/RESTORE-RSYNC.LOG


RESTORE-RSYNC-LOCAL.SH



#!/BIN/BASH

#############################################

## NAME : RESTORE-RSYNC-LOCAL.SH

## VERSION : 1.1

## DATE : 2011-11-08

## AUTHOR : LHAMMONDS

## PURPOSE : RESTORE ZIMBRA USING RSYNC AND THE LOCAL BACKUP.

## COMPATIBILITY : VERIFED ON UBUNTU SERVER 10.04.3 - 10.04.4 LTS, ZIMBRA 7.1.3 - 7.2.0 OSE

## REQUIREMENTS : MUST BE RUN AS ROOT USER, LAST RSYNC SHOULD BE THE OFFLINE VERSION.

## RUN FREQUENCY : MANUAL AS NEEDED.

## EXIT CODES : ERRORS DISPLAYED TO SCREEN.

################ CHANGE LOG #################

## DATE WHO WHAT WAS CHANGED

## ---------- --- ----------------------------

## 2011-10-18 LTH CREATED SCRIPT.

## 2011-10-31 LTH ADDED BETTER LOGGING, ERROR CHECKS, USER INPUT.

## 2011-11-08 LTH MOVE COMMON VARIABLES AND FUNTIONS TO EXTERNAL FILE.

#############################################
## IMPORT COMMON VARIABLES AND FUNCTIONS. ##

SOURCE /VAR/SCRIPTS/COMMON/STANDARD.CONF
LOGFILE="${TEMPDIR}/RESTORE-RSYNC.LOG"

LOCKFILE="${TEMPDIR}/RSYNC.LOCK"

RSYNCLOGFILE="${TEMPDIR}/RSYNC.LOG"

PRODROOT="/OPT"

OLDDIR="${BACKUPDIR}/ZIMBRA.OLD"

LOCALBACKUP="${BACKUPDIR}/ZIMBRA/ZIMBRA"

LOCALBACKUPDEV="/DEV/MAPPER/LVG-BAK"

NOBACKUP=0
#######################################

## FUNCTIONS ##

#######################################
FUNCTION F_CLEANUP()

{

IF [ -F ${LOCKFILE} ];THEN

## REMOVE LOCK FILE SO OTHER RSYNC JOBS CAN RUN.

RM ${LOCKFILE} 1>/DEV/NULL 2>&1

FI

}
FUNCTION F_CHECKSPACE()

{

## NEED TO CHECK AND SEE IF THERE IS ENOUGH SPACE AVAILABLE TO MOVE ZIMBRA TO A BACKUP LOCATION.

FREESPACE=`DF -K ${LOCALBACKUPDEV} | GREP ${LOCALBACKUPDEV} | AWK '{ PRINT $4 }'`

BACKUPSIZE=`DU -SK ${ZIMBRADIR} | AWK '{ PRINT $1 }'`
IF [ ${BACKUPSIZE} -GT ${FREESPACE} ]; THEN

ECHO "THERE IS NOT ENOUGH FREESPACE AVAILABLE TO ARCHIVE PRODUCTION ZIMBRA."

ECHO "ZIMBRA SIZE IS ${BACKUPSIZE} KB, FREE SPACE IS ${FREESPACE} KB"

ECHO ""

ECHO "TO OVERRIDE AND NOT MAKE A BACKUP 1ST, USE THE --NOBACKUP OPTION."

ECHO ""

ECHO "EXAMPLE: ${SCRIPTNAME} --NOBACKUP"

ECHO ""

F_CLEANUP

EXIT 1

FI

}
#######################################

## MAIN PROGRAM ##

#######################################
IF [ -F ${LOCKFILE} ]; THEN

# RSYNC LOCK FILE DETECTED. ABORT SCRIPT.

ECHO "RESTORE RSYNC ABORTED"

ECHO "THIS SCRIPT TRIED TO RUN BUT DETECTED THE LOCK FILE: ${LOCKFILE}"

ECHO "PLEASE CHECK TO MAKE SURE THE FILE DOES NOT REMAIN WHEN RSYNC IS NOT ACTUALLY RUNNING."

F_SENDMAIL "RESTORE RSYNC ABORTED" "THIS SCRIPT TRIED TO RUN BUT DETECTED THE LOCK FILE: ${LOCKFILE}NNPLEASE CHECK TO MAKE SURE THE FILE DOES NOT REMAIN WHEN RSYNC IS NOT ACTUALLY RUNNING."

EXIT 1

ELSE

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` ${SCRIPTNAME}" > ${LOCKFILE}

FI
CLEAR

ECHO ""
# DETERMINE IF WE ARE GOING TO BACKUP EXISTING FOLDER OR NOT.

IF [ "$1" = "--NOBACKUP" ]; THEN

NOBACKUP=1

ELSE

NOBACKUP=0

F_CHECKSPACE

FI
## REQUIREMENT CHECK: SCRIPT MUST RUN AS ROOT USER.

IF [ "$(ID -U)" != "0" ]; THEN

## FATAL ERROR DETECTED: DOCUMENT PROBLEM AND TERMINATE SCRIPT.

ECHO "ERROR: ROOT USER REQUIRED FOR RESTORE."

ECHO ""

F_CLEANUP

EXIT 1

FI
IF [ ! -F ${RSYNCLOGFILE} ]; THEN

## FATAL ERROR DETECTED: DOCUMENT PROBLEM AND TERMINATE SCRIPT.

ECHO "ERROR: CANNOT FIND LOG: ${RSYNCLOGFILE}"

ECHO "THIS LOG FILE IS REQUIRED TO DETERMINE STATUS OF LAST RSYNC JOB."

ECHO ""

F_CLEANUP

EXIT 1

FI


ECHO "THIS RESTORE METHOD CAN ONLY WORK IF THE LAST RSYNC BACKUP WAS"

ECHO "THE 'OFFLINE' VERSION WHICH ALLOWS FOR A COMPLETE BACKUP."

ECHO ""

ECHO "THE 'ONLINE' VERSION IS ONLY A PARTIAL BACKUP AND WILL NOT WORK."

ECHO ""

READ -P "THE NEXT STEP WILL TRY TO AUTO-DETECT THE LAST BACKUP. CONTINUE (Y/N)? "

IF [ "${REPLY}" != "Y" ]; THEN

ECHO "SCRIPT CANCELLED."

ECHO ""

F_CLEANUP

EXIT 1

FI

ECHO ""
TAIL -N1 ${RSYNCLOGFILE} | GREP -Q "OFFLINE RSYNC BACKUP EXIT CODE"

IF [ $? -EQ 0 ]; THEN

ECHO "LAST RSYNC SEEMS TO HAVE BEEN A GOOD OFFLINE BACKUP"

ELSE

ECHO "WARNING: THIS SCRIPT DID NOT SEE THE OFFLINE ENTRY AT THE END OF THE LOG FILE."

FI

ECHO ""
ECHO "--------------------------------------------------------"

TAIL -N5 ${RSYNCLOGFILE}

ECHO "--------------------------------------------------------"

ECHO ""
READ -P "DO YOU SEE 'OFFLINE RSYNC BACKUP EXIT CODE: 0' IN THE LOG ABOVE (Y/N)? "

IF [ "${REPLY}" != "Y" ]; THEN

ECHO "SCRIPT CANCELLED."

ECHO ""

F_CLEANUP

EXIT 1

FI
ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - RESTORE STARTED." | TEE -A ${LOGFILE}
STARTTIME="$(DATE +%S)"
## STOP ZIMBRA SERVICES.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- STOPPING ZIMBRA SERVICES." | TEE -A ${LOGFILE}

/ETC/INIT.D/ZIMBRA STOP
## KILL ANY ORPHANED ZIMBRA PROCESSES.

PKILL -9 -U ZIMBRA 1>/DEV/NULL 2>&1
IF [ ${NOBACKUP} -EQ 1 ]; THEN

## LEAVE CURRENT PRODUCTION FOLDER ALONE.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- 'NO BACKUP' OVERRIDE SPECIFIED, SKIPPING FOLDER MOVE." | TEE -A ${LOGFILE}

ELSE

## MOVE PRODUCTION FOLDER TO BACKUP LOCATION.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- MOVING ZIMBRA FROM ${ZIMBRADIR} TO ${OLDDIR}." | TEE -A ${LOGFILE}

MV ${ZIMBRADIR} ${OLDDIR}

RETURNVALUE=$?

IF [ ${RETURNVALUE} -NE 0 ]; THEN

## COULD NOT MOVE ZIMBRA TO BACKUP LOCATION.

## DOCUMENT ERROR AND TERMINATE SCRIPT.

ECHO ""

ECHO "ERROR: THE MOVE WAS NOT SUCCESSFUL. RETURN VALUE = ${RETURNVALUE}" | TEE -A ${LOGFILE}

ECHO ""

ECHO "COMMAND WAS 'MV ${ZIMBRADIR} ${OLDDIR}'" | TEE -A ${LOGFILE}

ECHO ""

ECHO "THE ZIMBRA SERVICES ARE CURRENTLY STOPPED AND AN UNKNOWN AMOUNT OF FILES WERE MOVED"

ECHO "FROM THE SOURCE. THAT MEANS THERE SOME FILES ARE STILL IN ${ZIMBRADIR}"

ECHO "AND SOME FILES WERE MOVED TO ${OLDDIR}"

ECHO "THIS NEEDS TO BE RESOLVED BEFORE YOU CAN START THE SERVICES BACK UP."

ECHO "EITHER MOVE THE FILES BACK OR DELETE ALL FILES AND RUN THE RESTORE."

F_CLEANUP

EXIT 99

FI

FI
## NOW THAT ZIMBRA IS OFFLINE, RSYNC CAN RESTORE ALL FILES.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- RESTORING FILES WITH RSYNC." | TEE -A ${LOGFILE}

RSYNC -APOGHK ${LOCALBACKUP} ${PRODROOT}

RETURNVALUE=$?

IF [ ${RETURNVALUE} -NE 0 ]; THEN

## RSYNC COMMAND FAILED. DISPLAY WARNING MESSAGE.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- ERROR: RSYNC RETURN VALUE = {$RETURNVALUE}" | TEE -A ${LOGFILE}

FI
IF [ ! -F ${ZIMBRADIR}/.INSTALL_HISTORY ]; THEN

## SOMETHING IS NOT RIGHT...AT LEAST THIS FILE SHOULD EXIST HERE.

## NOTE: THIS IS NOT A GUARENTEE ALL FILES WERE RESTORED, IT IS JUST A QUICK CHECK.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- ERROR: MISSING FILE(S). DID NOT FIND ${ZIMBRADIR}/.INSTALL_HISTORY" | TEE -A ${LOGFILE}

FI
## FIX PERMISSIONS.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- FIXING FILE OWNERSHIP AND PERMISSIONS." | TEE -A ${LOGFILE}

CHOWN -R ZIMBRA:ZIMBRA ${ZIMBRADIR}

${ZIMBRADIR}/LIBEXEC/ZMFIXPERMS
## START ZIMBRA SERVICES.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- STARTING ZIMBRA SERVICES." | TEE -A ${LOGFILE}

/ETC/INIT.D/ZIMBRA START
## CALCULATES DOWNTIME OF ZIMBRA SERVICES.

FINISHTIME="$(DATE +%S)"

ELAPSEDTIME="$(EXPR ${FINISHTIME} - ${STARTTIME})"

HOURS=$((${ELAPSEDTIME} / 3600))

ELAPSEDTIME=$((${ELAPSEDTIME} - ${HOURS} * 3600))

MINUTES=$((${ELAPSEDTIME} / 60))

SECONDS=$((${ELAPSEDTIME} - ${MINUTES} * 60))
ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- ZIMBRA RESTORE TIME: ${HOURS} HOUR(S) ${MINUTES} MINUTE(S) ${SECONDS} SECOND(S)" | TEE -A ${LOGFILE}
## SHOW STATUS OF ZIMBRA SERVICES.

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` --- STATUS OF ZIMBRA SERVICES:" | TEE -A ${LOGFILE}

SU - ZIMBRA -C "ZMCONTROL STATUS" | TEE -A ${LOGFILE}
IF [ -D ${OLDDIR} ]; THEN

ECHO -E "NNDON'T FORGET TO PURGE ${OLDDIR} ONCE EVERYTHING IS RUNNING SMOOTHLY AGAIN.NN"

FI
F_CLEANUP

ECHO "`DATE +%Y-%M-%D_%H:%M:%S` - RESTORE COMPLETED." | TEE -A ${LOGFILE}


SAMPLE OUTPUT FROM SCRIPT:



2011-10-18_16:26:40 - RESTORE STARTED.

2011-10-18_16:26:40 --- STOPPING ZIMBRA SERVICES.

HOST MAIL.MYDOMAIN.COM

STOPPING STATS...DONE.

STOPPING MTA...DONE.

STOPPING SPELL...DONE.

STOPPING SNMP...DONE.

STOPPING CBPOLICYD...DONE.

STOPPING ARCHIVING...DONE.

STOPPING ANTIVIRUS...DONE.

STOPPING ANTISPAM...DONE.

STOPPING IMAPPROXY...DONE.

STOPPING MEMCACHED...DONE.

STOPPING MAILBOX...DONE.

STOPPING LOGGER...DONE.

STOPPING ZMCONFIGD...DONE.

STOPPING LDAP...DONE.

2011-10-18_16:27:22 --- MOVING ZIMBRA FROM /OPT/ZIMBRA TO /TEMP/ZIMBRA.OLD.

2011-10-18_16:27:22 --- RESTORING FILES WITH RSYNC.

2011-10-18_16:31:53 --- FIXING FILE OWNERSHIP AND PERMISSIONS.

2011-10-18_16:31:55 --- STARTING ZIMBRA SERVICES.

HOST MAIL.MYDOMAIN.COM

STARTING LDAP...DONE.

STARTING ZMCONFIGD...DONE.

STARTING LOGGER...DONE.

STARTING MAILBOX...DONE.

STARTING ANTISPAM...DONE.

STARTING ANTIVIRUS...DONE.

STARTING SNMP...DONE.

STARTING SPELL...DONE.

STARTING MTA...DONE.

STARTING STATS...DONE.

2011-10-18_16:33:25 --- ZIMBRA RESTORE TIME: 0 HOUR(S) 6 MINUTE(S) 45 SECOND(S)

2011-10-18_16:33:25 --- STATUS OF ZIMBRA SERVICES:

HOST MAIL.MYDOMAIN.COM

ANTISPAM RUNNING

ANTIVIRUS RUNNING

LDAP RUNNING

LOGGER RUNNING

MAILBOX RUNNING

MTA RUNNING

SNMP RUNNING

SPELL RUNNING

STATS RUNNING

ZMCONFIGD RUNNING

2011-10-18_16:33:55 - RESTORE COMPLETED.

4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

Scenario #4 Restore existing server from an offsite location
/var/scripts/prod/rsync-restore.sh



#!/bin/bash

#############################################

## Name : rsync-restore.sh

## Version : 1.0

## Date : 2011-11-08

## Author : LHammonds

## Purpose : Restore Zimbra using rsync from a remote archive.

## Compatibility : Verified on Ubuntu Server 10.04.3 - 10.04.4 LTS, Zimbra 7.1.2 - 7.2.0 OSE

## Requirements : Must be root user, p7zip-full (if ARCHIVEMETHOD=tar.7z)

## Run Frequency : Manual as needed.

## Exit Codes :

## 0 = Success or non-critical problem

## 1 = Archive folder does not exist

## 2 = Archive extration failed

## 3 = Zimbra restore failure

## 99 = Move production to temp directory failure (bad)

################ CHANGE LOG #################

## DATE WHO WHAT WAS CHANGED

## ---------- --- ----------------------------

## 2011-11-08 LTH Created script.

#############################################
## Import common variables and functions. ##

source /var/scripts/common/standard.conf
LOGFILE="${TEMPDIR}/rsync-restore.log"

LOCKFILE="${TEMPDIR}/rsync.lock"

ARCHIVEDIR="${OFFSITEDIR}/zimbra"

OLDDIR="${BACKUPDIR}/zimbra.old"

NOBACKUP=0
#######################################

## FUNCTIONS ##

#######################################
function f_cleanup()

{

if [ -f ${LOCKFILE} ];then

## Remove lock file so other rsync jobs can run.

rm ${LOCKFILE} 1>/dev/null 2>&1

fi

}
function f_checkspace()

{

## Need to check and see if there is enough space available to move Zimbra to a backup location.

FREESPACE=`df -k ${BACKUPDIR} | grep ${BACKUPDIR} | awk '{ print $4 }'`

BACKUPSIZE=`du -sk ${ZIMBRADIR} | awk '{ print $1 }'`
if [ ${BACKUPSIZE} -gt ${FREESPACE} ]; then

echo "There is not enough freespace available to archive production Zimbra."

echo "Zimbra size is ${BACKUPSIZE} kb, Free space is ${FREESPACE} kb"

echo ""

echo "To override and not make a backup 1st, use the --nobackup option."

echo ""

echo "Example: ${SCRIPTNAME} --nobackup"

echo ""

f_cleanup

exit 1

fi

}
function f_emergencyexit()

{

## Purpose: Exit script as cleanly as possible.

## Parameter #1 = Error Code.
if [ -f ${REMOTEDIR}/online.txt ]; then

## Dismount the remote site.

f_umount

fi

echo -e "Zimbra restore aborted. EXIT CODE: ${1}
"

exit $1

}
#######################################

## MAIN PROGRAM ##

#######################################
if [ -f ${LOCKFILE} ]; then

## Restore lock file detected. Abort script.

echo "Restore aborted"

echo "This script tried to run but detected the lock file: ${LOCKFILE}"

echo "Please check to make sure the file does not remain when rsync or restore is not actually running."

f_sendmail "Zimbra Restore aborted" "This script tried to run but detected the lock file: ${LOCKFILE}

Please check to make sure the file does not remain when rsync/restore is not actually running."

exit 1

else

echo "`date +%Y-%m-%d_%H:%M:%S` ${SCRIPTNAME}" > ${LOCKFILE}

fi
clear

echo ""
## Determine if we are going to backup existing folder or not.

if [ "$1" = "--nobackup" ]; then

NOBACKUP=1

else

NOBACKUP=0

##

f_checkspace

fi
## Requirement Check: Script must run as root user.

if [ "$(id -u)" != "0" ]; then

## FATAL ERROR DETECTED: Document problem and terminate script.

echo "ERROR: Root user required for restore."

echo ""

f_cleanup

exit 1

fi
## Mount the remote site.

f_mount
## Check to make sure the archive folder exists.

if [ ! -d "${ARCHIVEDIR}" ]; then

## ERROR: Archive folder does not exist.

echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: The archive folder does not exist! ${ARCHIVEDIR}, EC=1" | tee -a ${LOGFILE}

f_cleanup

f_emergencyexit 1

fi
## Define user prompt using the special PS3 variable.

PS3="Type number for the desired archive or 'q' to quit: "
echo " Z I M B R A R E S T O R E"

echo " ---------------------------"

## Get sorted list of all archives (newest at the bottom).

FILELIST=$(find ${ARCHIVEDIR}/*.${ARCHIVEMETHOD} -maxdepth 1 -type f | sort -f)
## Prompt user to select a file to use.

## NOTE: If it is a long list, user can scroll up if

## using PuTTY to see older files.

select GETFILE in ${FILELIST}; do

if [ "${GETFILE}" != "" ]; then

FILENAME=${GETFILE}

fi

break

done
if [ "${FILENAME}" = "" ]; then

## User opted to quit.

echo -e "Exiting restore program.
"

f_cleanup

f_umount

exit 0

fi
echo -e "
Selected file: ${FILENAME}
"

echo -e " This restore will shutdown Zimbra and make it"

echo -e " unavailable while it is being restored.
"

read -p "Are you absolutely sure you wish to restore (y/n)? "
if [ "${REPLY}" != "y" ]; then

echo -e "

Restore aborted.

"

f_cleanup

exit 0

fi
echo "`date +%Y-%m-%d_%H:%M:%S` - Restore started." | tee -a ${LOGFILE}
StartTime="$(date +%s)"
## Stop Zimbra Services.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Stopping Zimbra services." | tee -a ${LOGFILE}

/etc/init.d/zimbra stop
## Kill any orphaned Zimbra processes.

pkill -9 -u zimbra 1>/dev/null 2>&1
if [ ${NOBACKUP} -eq 1 ]; then

## Leave current production folder alone.

echo "`date +%Y-%m-%d_%H:%M:%S` --- 'No Backup' override specified, skipping folder move." | tee -a ${LOGFILE}

else

## Move production folder to backup location.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Moving Zimbra from ${ZIMBRADIR} to ${OLDDIR}." | tee -a ${LOGFILE}

mv ${ZIMBRADIR} ${OLDDIR}

RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## Could not move Zimbra to backup location.

## Document error and terminate script.

echo ""

echo "ERROR: The move was not successful. Return value = ${RETURNVALUE}" | tee -a ${LOGFILE}

echo ""

echo "COMMAND was 'mv ${ZIMBRADIR} ${OLDDIR}'" | tee -a ${LOGFILE}

echo ""

echo "The Zimbra services are currently stopped and an unknown amount of files were moved"

echo "from the source. That means there some files are still in ${ZIMBRADIR}"

echo "and some files were moved to ${OLDDIR}"

echo "This needs to be resolved before you can start the services back up."

echo "Either move the files back or delete all files and run the restore."

f_cleanup

exit 99

fi

fi
## Now that Zimbra is offline, we can restore all files.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Restoring files from ${FILENAME}" | tee -a ${LOGFILE}
if [ ! -d ${ZIMBRADIR} ]; then

mkdir -p ${ZIMBRADIR}

fi
## Extract the entire contents of the archive back to its original location.

case "${ARCHIVEMETHOD}" in

tar.7z)

7za x -so -w/${TEMPDIR} ${FILENAME} | tar -C ${ZIMBRADIR} --extract --strip-components=4 --file -

;;

tgz)

tar --extract -C ${ZIMBRADIR} --strip-components=4 --file=${FILENAME}

;;

*)

tar --extract -C ${ZIMBRADIR} --strip-components=4 --file=${FILENAME}

;;

esac

RETURNVALUE=$?

if [ ${RETURNVALUE} -ne 0 ]; then

## tar extract command failed. Display warning message.

echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: tar extract return value = {$RETURNVALUE}" | tee -a ${LOGFILE}

f_cleanup

f_emergencyexit 2

fi
if [ ! -f ${ZIMBRADIR}/.install_history ]; then

## Something is not right...at least this file should exist here.

## NOTE: This is not a guarentee all files were restored, it is just a quick check.

echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: Missing file(s). Did not find ${ZIMBRADIR}/.install_history" | tee -a ${LOGFILE}

fi
## Fix permissions.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Fixing file ownership and permissions." | tee -a ${LOGFILE}

chown -R zimbra:zimbra ${ZIMBRADIR}

${ZIMBRADIR}/libexec/zmfixperms
## Start Zimbra services.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Starting Zimbra services." | tee -a ${LOGFILE}

/etc/init.d/zimbra start
## Calculates downtime of Zimbra services.

FinishTime="$(date +%s)"

ElapsedTime="$(expr ${FinishTime} - ${StartTime})"

Hours=$((${ElapsedTime} / 3600))

ElapsedTime=$((${ElapsedTime} - ${Hours} * 3600))

Minutes=$((${ElapsedTime} / 60))

Seconds=$((${ElapsedTime} - ${Minutes} * 60))
echo "`date +%Y-%m-%d_%H:%M:%S` --- Zimbra restore time: ${Hours} hour(s) ${Minutes} minute(s) ${Seconds} second(s)" | tee -a ${LOGFILE}
## Show status of Zimbra services.

echo "`date +%Y-%m-%d_%H:%M:%S` --- Status of Zimbra services:" | tee -a ${LOGFILE}

su - zimbra -c "zmcontrol status" | tee -a ${LOGFILE}
if [ -d ${OLDDIR} ]; then

echo -e "

Don't forget to purge ${OLDDIR} once everything is running smoothly again.

"

fi
f_cleanup

## Dismount the remote site.

f_umount
echo "`date +%Y-%m-%d_%H:%M:%S` - Restore completed." | tee -a ${LOGFILE}

4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

Scenario #5 Restore to new server

** UNFINISHED **
4414LHammonds
Advanced member
Advanced member
Posts: 148
Joined: Sat Sep 13, 2014 2:14 am

My Notes for Installing Zimbra OSE on Ubuntu Server 10.04 LTS

Post by 4414LHammonds »

Crontab
I would not advise anyone to ever "edit" a live crontab schedule by typing "crontab -e" but rather edit a saved schedule file and then load the schedule file. This will allow you to make backups of the schedule so you can always go back to a known-good schedule or at least back to the way it was before you made a change...assuming you always work with a copy of the schedule 1st.
Here is my root crontab scheduling file:
/var/scripts/data/crontab.root


########################################

# Name: Crontab Schedule for root user

# Author: LHammonds

############# Update Log ###############

# 2011-10-29 - LTH - Created schedule

# 2011-11-22 - LTH - Added shell and path

# 2012-01-30 - LTH - Added time adjustment

# 2012-05-02 - LTH - Added check-space

# 2012-05-05 - LTH - Added check mailbox size

########################################

#

# Import Active Directory users (run every minute)

0-59 * * * * /var/scripts/prod/import-ad.sh > /dev/null 2>&1

#

# Update the Global Address List for iPhone usage.

#

0 23 * * * /var/scripts/prod/gal-sync.sh > /dev/null 2>&1

#

# Partial backup of Zimbra to a local folder without taking it offline.

#

0 8-18 * * * /var/scripts/prod/rsync-online.sh > /dev/null 2>&1

#

# Backup Zimbra to a local folder, archive and store offsite.

#

0 23 * * * /var/scripts/prod/rsync-offline.sh > /dev/null 2>&1

#

# Backup individual mailboxes to a local folder, archive and store offsite.

#

0 6-18 * * * /var/scripts/prod/zm-user-backup.sh > /dev/null 2>&1

#

# Daily check for available space on /opt

#

0 1 * * * /var/scripts/prod/check-storage.sh opt 5 1 > /dev/null 2>&1

#

# Daily check for available space on /var/backup

#

0 2 * * * /var/scripts/prod/check-storage.sh bak 5 1 > /dev/null 2>&1

#

# Daily check for available space on /var/temp

#

0 3 * * * /var/scripts/prod/check-storage.sh temp 5 1 > /dev/null 2>&1

#

# Daily check for mailbox size notifications

#

0 6 * * * /var/scripts/prod/mailbox-size-notification.sh > /dev/null 2>&1


Once you have created the file, make sure appropriate permissions are set by typing the following:



chown root:root /var/scripts/data/crontab.root

chmod 0600 /var/scripts/data/crontab.root


To enable the root schedule using this file, type the following:
crontab -u root /var/scripts/data/crontab.root
To disable the root schedule, type the following:



touch /tmp/deleteme

crontab -u root /tmp/deleteme

rm /tmp/deleteme


If you need to modify the schedule, make a backup copy 1st. For example:


cp /var/scripts/data/crontab.root /var/scripts/prod/2011-11-28-crontab.root

vi /var/scripts/data/crontab.root (make your changes)

crontab -u root /var/scripts/data/crontab.root

Post Reply