Хабрахабр

Настройка резервного копирования и восстановления Zimbra OSE целиком и отдельными ящиками, не используя Zexstras

1. С чего начать

С чего начинается резервное копирование? Планирование. При резервировании любой системы, необходимо составить план резервного копирования: что именно, как часто, как долго хранить, хватит ли свободного пространства? Из ответов на эти вопросы вытекает ответ на главный вопрос – чем бэкапить?

Делать бэкапы тем же Veeam по расписанию, и не думать о сложностях. Если свободного пространства много – можно хранить целиком виртуальную машину. Veeam у меня, конечно же, развернут, но им я делаю резервные копии лишь тех систем, которые либо невозможно, либо проблематично и очень долго разворачивать из резервных копий. Но как по мне, так это расточительство, я привык делать все максимально сжато и, по возможности, экономично.

Про скрипты средств управления виртуальной средой просто многозначительно промолчу.

И, при ближайшем рассмотрении его функционала, я понял, что его мне будет более, чем достаточно. У Zimbra есть инструмент zmmailbox. И мне понравилась возможность делать бэкапы критичных почтовых ящиков отдельно от бэкапа всей системы. Он умеет резервировать и восстанавливать ящики даже на живой системе. К тому же с бэкапа всей системы, в случае с Zimbra, крайне сложно восстановиться. Таким образом пространство, занимаемое резервными копиями, будет ограничено размером заархивированных почтовых ящиков, помноженным на количество дней «глубины бэкапа», а не объемом всей системы, помноженной на то же количество дней. По-моему, это наименее затратный во всех отношениях сценарий.
Гораздо проще скопировать виртуальную машину с помощью Veeam или средств управления виртуальной средой (Hyper-V, ESXI, вписать нужное) сразу после настройки системы, и положить «на полочку», чтобы в критичный момент можно было быстро развернуть почти ничего не весящую ВМ и залить в нее бэкапы ящиков.

2. Исходные данные:

ОС сервера: CentOS 7

По поводу ОС

Работа ведется в основном с командлетами Zimbra, так что отличия настройки будет минимальны. На самом деле разница между CentOS7 и любой другой системой будет заключаться исключительно в командах серверу на установку пакетов, и, возможно, расположении некоторых файлов.

Домен Zimbra: zimbramail.home.local
Имя пользователя и пароль для доступа к расшаренной папке: ZimbraBackUp / 123123
Путь к расшаренной папке: \\BackUpServer1\ZM\
Путь монтирования шары на хосте Zimbra: /mnt/ZM/

3. Настройка

Итак, начнем!

При желании можно сливать резервные копии куда угодно, но у меня все настроено так, что большинство бэкапов пишутся именно на BackUpServer1.home.local. Бэкапы будем писать на сервер под управлением Windows, в расшаренную папку. Так что:

Имя пользователя ZimbraBackUp, пароль, условно, 123123. 1) Создаем в домене пользователя для доступа к расшаренной папке на этом сервере, чтобы можно было смонтировать ее на сервере Zimbramail.home.local.

Путь к шаре будет таким: \\BackUpServer1\ZM\ 2) На сервере BackUpServer1 создаем в хранилище директорию \ZM\, и расшариваем ее, давая права на изменение для пользователя ZimbraBackUp.

Чтобы папка монтировалась автоматически, нужно поправить файл /etc/fstab, добавив в него строку: 3) Монтируем шару к серверу Zimbramail.home.local.

//BackUpServer/ZM /mnt/ZM cifs user,uid=500,rw,suid,username=ZimbraBackUp,password=123123 0 0

Но сначала надо проверить, работает ли монтирование:

$ mount -t cifs //BackUpServer/ZM /mnt/ZM -o user=ZimbraBackUp,password=123123

Часто возникает ошибка примерно такого вида:

mount: wrong fs type, bad option, bad superblock on //BackUpServer1/ZM/,
missing codepage or helper program, or other error
(for several filesystems (e.g. nfs, cifs) you might
need a /sbin/mount.<type> helper program)
In some cases useful info is found in syslog - try
dmesg | tail or so.

Исправить можно установкой cifs-utils:

$ yum install cifs-utils

После настройки рекомендую перезагрузить сервер.

4) Создаем 3 файла-скрипта: FullBackUp.sh HandBackUp.sh Restore.sh

И третий скрипт – восстановление одного или сразу всех ящиков. Первый файл будет использоваться для автоматического создания резервных копий по расписанию, второй для возможности резервного копирования отдельных ящиков, или просто ручного запуска «а вдруг что». Я постарался максимально прокомментировать работу скриптов и прописал логирование.

Содержание файла FullBackUp.sh:

#!/bin/bash
#Куда положить бэкап
Path="/mnt/ZM/BackUps"
#Куда положить архив бэкапа
ArchPath="/mnt/ZM/Archive"
#Куда положить месячный бэкап
MPath="/mnt/ZM/Mounthly"
#Название домена Zimbra
ZDomain="zimbramail.home.local"
#Список ящиков
MBoxes="/mnt/ZM/MBoxesList"
#Текущая дата
CDate=$(date +%d-%m-%Y)
#Запоминаем день месяца
MDay=$(date +%d)
#Куда писать логи
log="/mnt/ZM/BackUpLog.txt"
echo -en "BackUp ALL MailBoxes started in $(date +%T)\n" >> $log
#Проверка не существования каталога для резервного копирования
if [ ! -d $Path ]; then #Создание каталога хранения резервных копий echo "Создание каталога хранения резервных копий..." mkdir -p $Path if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "BackUp dirctory was created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "BackUp dirctory was NOT created in $(date +%T)\n" >> $log fi
else
echo "Каталог хранения резервных копий существует, проверка существования каталога на сегодняшнее число..."
fi
#Првоерка не существования каталога на сегодняшнюю дату
if [ ! -d $Path/$CDate ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo #Создание каталога хранения резервных копий на сегодняшнее число echo "Создание каталога хранения резервных копий на сегодняшнее число..." mkdir -p $Path/$CDate if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "BackUp CDate dirctory was created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "BackUp CDate dirctory was NOT created in $(date +%T)\n" >> $log fi
else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo "Каталог хранения резервных копий существует, запись списка ящиков в файл..."
fi
#Запись списка ящиков в файл
/opt/zimbra/bin/zmprov -l gaa $ZDomain > $MBoxes
#Вывод результата записи списка
if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Mail Boxes list created in $(date +%T)\n" >> $log
else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo -en "Mail Box list is NOT created! in $(date +%T)\n" >> $log exit
fi
#создание резервных копий каждого ящика из списка
for MailBox in $( cat $MBoxes); do echo "Создание резервной копии ящика $MailBox..." /opt/zimbra/bin/zmmailbox -z -m $MailBox getRestUrl "//?fmt=tgz" > $Path/$CDate/$MailBox if [ $? -eq 0 ]; then #Вывод результата создания резервной копии для каждого ящика echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Mail Box $MailBox BackUp created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo -en "Mail Box $MailBox BackUp is NOT created! in $(date +%T)\n" >> $log fi
done
#Очищаем файл со списком ящиков
echo "Очистка файла со споском ящиков..."
echo -n > $MBoxes
if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "File $MBoxes clear\n" >> $log
else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "File $MBoxes can NOT be cleared\n" >> $log
fi
#Создание архива и работа с архивами
#Проверка не существования каталога для архивирвоания
if [ ! -d $ArchPath ]; then #Создание каталога хранения архивов echo "Создание каталога хранения архивов..." mkdir -p $ArchPath if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Archive dirctory was created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Archive dirctory was NOT created in $(date +%T)\n" >> $log fi
else
echo "Каталог хранения архивов существует, архививрование..."
fi
tar -czf $ArchPath/$CDate.tar $Path/$CDate
if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Archive created in $(date +%T)\n" >> $log #Каждое первое число месяца копирование архива на долгосрочное хранение if [ "$MDay" = 1 ]; then #Проверка существования каталога хранения долгосрочных архивов if [ ! -d $ArchPath ]; then #Создание каталога хранения долговрочных архивов echo "Создание каталога хранения долгосроных архивов..." mkdir -p $ArchPath if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Long saving dirctory was created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Long saving dirctory was NOT created in $(date +%T)\n" >> $log fi else #Каталог существует echo "Каталог долгосрочного хранения архивов существует, копирование архива на долгосрочное хранение..." fi cp $ArchPath/$CDate.tgz $MPath/$CDate if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Archive is copied in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Archive is NOT copied in $(date +%T)\n" >> $log fi echo "Удаление старых резервных копий (старше 1 недели)..." #Удаление каталогов, содержащих резервные копии, старше недели find $Path -atime +7 | xargs rm -d if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Old BackUps files was deleted\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Old BackUps files is NOT deleted in $(date +%T)\n" >> $log fi #Удаление старых архивов бэкапов (старше 2 месяцев) echo "Удаление старых архивов резервных копий (старше 2 месяцев)..." find $Path -atime +61 | xargs rm -f if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Old BackUps archives was deleted\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Old BackUps archives is NOT deleted in $(date +%T)\n" >> $log fi fi
else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Archive is NOT created in $(date +%T)\n" >> $log
fi
echo "BackUp job finished in $(date +%T)"
#запись в лог-файл времени окончания резервного копирования
echo -en "BackUp job finished in $(date +%T) $(date +%T)\n" >> $log
echo -en "_____________________________________________\n" >> $log

Содержание файла HandBackUp.sh:

#!/bin/bash
#Куда положить бэкап
Path="/mnt/ZM/BackUps"
#Куда положить архив бэкапа
ArchPath="/mnt/ZM/Archive"
#Название домена Zimbra
ZDomain="zimbramail.home.local"
#Список ящиков
MBoxes="/mnt/ZM/MBoxesList"
#Текущая дата
CDate=$(date +%d-%m-%Y)
#Куда писать логи
log="/mnt/ZM/BackUpLog.txt"
read -p "Введите имя почтового ящика (без указания домена), или ALL для резервного копирования всех почтовых ящиков: " A
if [[ "$A" = "ALL" || "$A" = "all" ]]; then echo -en "BackUp started in $(date +%T)\n" >> $log #Запись списка ящиков в файл echo "Запись списка ящиков в файл..." /opt/zimbra/bin/zmprov -l gaa $ZDomain > $MBoxes if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Mail Boxes list created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo -en "Mail Box list is NOT created! in $(date +%T)\n" >> $log exit fi if ! [ -d $Path/$Date ]; then #Создание каталога резервного копирования mkdir -p $Path/$CDate/ echo -en "BackUp directory created in $(date +%T)\n" >> $log else #Создание резервных копий каждого ящика из списка echo "Создание резервных копий каждого ящика из списка" for MailBox in $( cat $MBoxes); do echo "Создание резервной копии ящика $MailBox..." /opt/zimbra/bin/zmmailbox -z -m $MailBox getRestUrl "//?fmt=tgz" > $Path/$CDate/$MailBox if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Mail Box $MailBox BackUp created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo -en "Mail Box $MailBox BackUp is NOT created! in $(date +%T)\n" >> $log fi done fi
else MailBox="$A@$ZDomain" #Проверка существования запрошенного ящика echo "Проверка существования запрошенного ящика..." Result=$(/opt/zimbra/bin/zmprov getMailboxInfo $MailBox) if [ $? -eq 0 ]; then #Запрошенный ящик существует echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo "Запрошенный ящик $MailBox существует, резервное копирование..." echo -en "Required Mail Box $MailBox exist $(date +%T)\n" >> $log #Проверка существования каталога для резервного копирования if ! [ -d $Path/$Date ]; then #Создание резервной копии ящика mkdir -p $Path/$CDate/ echo -en "BackUp directory created in $(date +%T)\n" >> $log else #Создание резервной копии ящика $MailBox /opt/zimbra/bin/zmmailbox -z -m $MailBox getRestUrl "//?fmt=tgz" > $Path/$CDate/$MailBox if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Mail Box $MailBox BackUp created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo -en "Mail Box $MailBox BackUp is NOT created! in $(date +%T)\n" >> $log fi fi else #Запрошенный ящик не существовует - выход echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo "Запрошенный ящик $MailBox не существует. Завершение работы скрипта" echo -en "Required Mail Box $MailBox is not exist\n" >> $log exit fi
fi
read -p "Хотите запустить архивацию резервной копии ящика $MailBox? [N]: " F
if [[ "$F" = "Y" || "$F" = "y" ]]; then #Проверка не существования каталога для архивирвоания if [ ! -d $ArchPath ]; then #Создание каталога хранения резервных копий echo "Создание каталога хранения архивов..." mkdir -p $ArchPath if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Archive dirctory was created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Archive dirctory was NOT created in $(date +%T)\n" >> $log fi else echo "Каталог хранения архивов существует, архививрование..." fi #Создание архива резервной копии echo "Архивирование резервной копии..." if [[ "$A" = "ALL" || "$A" = "all" ]]; then tar -czf $ArchPath/$CDate.tar $Path/$CDate if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Archive created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Archive is NOT created in $(date +%T)\n" >> $log fi else tar -czf $ArchPath/$MailBox.tar $Path/$CDate/$MailBox if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Archive created in $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Archive is NOT created in $(date +%T)\n" >> $log fi fi
else
echo "Архив создан не будет"
echo -en "User decline archive creating\n" >> $log
fi
#Очищаем файл со списком ящиков
echo "Очистка файла со споском ящиков..."
echo -n > $MBoxes
if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo
else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo
fi
echo "BackUp job finished in $(date +%T) $(date +%T)"
#запись в лог-файл времени окончания резервного копирования
echo -en "BackUp job finished in $(date +%T) $(date +%T)\n" >> $log
echo -en "_____________________________________________\n" >> $log

Содержание файла Restore.sh:

#!/bin/bash
#Где лежат бэкапы
Path="/mnt/ZM/BackUps"
#Название домена Zimbra
ZDomain="zimbramail.home.local"
#Список ящиков
MBoxes="/mnt/ZM/MBoxesList"
#Куда писать логи
log="/mnt/ZM/RestoreLog.txt"
read -p "Дата резервной копии, которую необходимо восстановить в формате 02-09-2001: " Date
if ! [ -d $Path/$Date ]; then
echo "Нет резервных копий на указанную дату."
echo -en "No BackUp file at $Date $(date +%T)\n" > $log
exit
fi
read -p "Введите имя почтового ящика (без указания домена), или ALL для восстановления всех почтовых ящиков на указанную дату: " A
if [[ "$A" = "ALL" || "$A" = "all" ]]; then echo -en "Restore started in $(date +%T)\n" >> $log #Запись списка ящиков в файл ls "$Path/$Date" > $MBoxes for MailBox in $( cat $MBoxes); do #Проверка существования ящика echo "Проверка существования ящика $MailBox" Result=$(/opt/zimbra/bin/zmprov getMailboxInfo $MailBox) if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]" echo echo -en "Start restore job for $MailBox $(date +%T)\n" >> $log echo "Ящик $MailBox существует. Восстановление..." else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Mail Box $MailBox does not exist, creating Mail Box $MailBox $(date +%T)\n" >> $log echo "Ящик $MailBox не существует. Создание ящика $MailBox..." #Проверка создания ящика Result=$(/opt/zimbra/bin/zmprov ca $MailBox 12345678 displayName "$MailBox") if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]" echo echo -en "Mail Box $MailBox is created, starting restore $(date +%T)\n" >> $log echo "Ящик $MailBox создан успешно. Восстановление..." else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Can NOT create Mail Box $MailBox ! $(date +%T)\n" >> $log echo "Ящик $MailBox создать не удалось." fi fi #Восстановление ящика Result=$(/opt/zimbra/bin/zmmailbox -z -m $MailBox postRestURL "//?fmt=tgz&resolve=replace" $Path/$Date/$MailBox) if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Ящик $MailBox восстановлен в $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo -en "Ящик $MailBox НЕ восстановлен! $(date +%T)\n" >> $log fi done
else #Проверка существования запрошенной резервной копии MailBox="$A@$ZDomain" if [ -a $Path/$Date/$MailBox ]; then #Проверка существования ящика echo "Проверка существования ящика $MailBox..." Result=$(/opt/zimbra/bin/zmprov getMailboxInfo $MailBox) if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]" echo echo -en "Start restore job for $MailBox $(date +%T)\n" >> $log echo "Ящик $MailBox существует. Восстановление..." else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Mail Box $MailBox does not exist $(date +%T)\n" >> $log echo "Ящик $MailBox не существует." read -p "Хотите создать почтовый ящик с указанным именем и восстановить в него резервную копию? [N]: " B if [[ "$B" = "Y" || "$B" = "y" ]]; then echo "Создание почтового ящика $MailBox..." Result=$(/opt/zimbra/bin/zmprov ca $MailBox 12345678 displayName "$MailBox") #Проверка создания ящика if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]" echo echo -en "Mail Box $MailBox is created, starting restore $(date +%T)\n" >> $log echo "Ящик $MailBox создан успешно. Восстановление..." else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo echo -en "Can NOT create Mail Box $MailBox ! $(date +%T)\n" >> $log echo "Ящик $MailBox создать не удалось. Завершение работы скрипта..." exit fi else #Ящик не будет создан, нечего восстанавливать. Выход echo "Ящик не будет создан. Завершение работы скрипта" exit fi fi #Восстановление ящика Result=$(/opt/zimbra/bin/zmmailbox -z -m $MailBox postRestURL "//?fmt=tgz&resolve=replace" $Path/$Date/$MailBox) if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo echo -en "Ящик $MailBox восстановлен в $(date +%T)\n" >> $log else echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]" echo echo -en "Ящик $MailBox НЕ восстановлен! $(date +%T)\n" >> $log fi else #Запрошенной резервной копии не существует echo "Запрошенной резервной копии не существует. Завершение работы скрипта" echo -en "Required BackUp file is not exist\n" >> $log exit fi
fi #Очищаем файл со списком ящиков
echo "Очистка файла со споском ящиков..."
Result(echo -n > $MBoxes)
if [ $? -eq 0 ]; then echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]" echo
else echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]" echo
fi
echo "BackUp job finished in $(date +%T) $(date +%T)"
#запись в лог-файл времени окончания резервного копирования
echo -en "Restore job complete in $(date +%T)\n" >> $log
echo -en "____________________________________\n" >> $log

Тут есть одна тонкость. Если создавать и редактировать файлы скриптов для bash под Windows, то при попытке запустить скрипт будет выпадать ошибка: /bin/sh^M: bad interpreter: No such file or directory, которая заключается в том, что редакторы, работающие под Windows, добавляют в конце строки символ возврата каретки «CR\LF», который редакторы в Linux не отображают. Но символ этот там есть, и никуда не делся. Чтобы избавиться от ошибки и удалить лишние символы делаем следующее:

$ cat your-script.sh | tr -d '\r' > corrected-your-script.sh

Ну или можно воспользоваться утилитой dos2unix, но ее еще надо установить:

$ yum install dos2unix
$ dos2unix your-script.sh

5) Делаем скрипты исполняемыми:

$ chmod 0740 /opt/zimbra/BkUpRestScripts/FullBackUp.sh
$ chmod 0740 /opt/zimbra/BkUpRestScripts/HandBackUp.sh
$ chmod 0740 /opt/zimbra/BkUpRestScripts/Restore.sh

6) Рекомендую руками запустить скрипты и проверить, работают ли они, и как они работают.

7) Создать задачу в CRON для ежедневного резервного копирования почтовых ящиков:

10 0 * * * root /opt/zimbra/ BkUpRestScripts/FullBackUp.sh

8) Наслаждаться

4. Работа скриптов

На случай, если комментарии в самих скриптах не помогли.

1) Скрипт FullBaclUp.sh:

В начале определяются переменные, какая за что отвечает – все прокомментировано.

Делается вывод в лог-файл и на экран (если запущен руками) о успехе или не успехе создания каталога. Далее следует проверка отсутствия каталога для резервного копирования, если он не существует – создается.

Если его нет — создается, так же вывод на экран и в лог результата создания каталога. Проверка отсутствия каталога с сегодняшней датой.

Он нужен для последовательного резерварования каждого ящика. Запись в файл всех существующих почтовых ящиков Zimbra. Вывод на экран результата выполнения команды.

С выводом результата выполнения на экран и в лог-файл. Создание бэкапа для каждого ящика из полученного списка.

Так как с этим файлом работают все 3 скрипта, то целесообразно чистить его после каждого прогона, чтобы не было неожиданностей. Очистка файла со списком ящиков. Можно чистить его и перед началом работы скрипта, но мне как-то привычнее не хранить лишних данных после выполнения работы, а делать одно и то же до и после работы скрипта – легкая степень шизофрении.

Далее блок по созданию сжатого архива.

Проверка отсутствия каталога хранения архивов, его создание при отсутствии и вывод на экран и в лог результата создания.

Архивирование.

Я предпочитаю долгосрочно хранить бэкапы за 1е числа всех месяцев, мне этого для работы достаточно. Проверка «а не первое ли сегодня число?». А вот сверху поставлено условие хранения бэкапов за весь период работы почтового сервера, так что лежать им там веки вечные. Можно и по неделям хранить, но зачастую это избыточно. И чтобы его туда скопировать – нужно проверить, нет ли такого каталога, и если нет – создать его, о чем сообщать на экран и в лог-файл. Если число – первое, то полученный архив копируется в отдельный каталог “ Mounthly ”.

Результат удаления выводится на экран и в лог-файл. Далее осуществляется чистка хранилища – удаляются все резервные копии старше 2х недель, а также архивы, старше 61 дня.

После чего скрипт пишет время завершения работы в лог-файл и на экран, и завершает свою работу.

2) Скрипт HandBackUp.sh:

В начале так же определяются переменные, так же прокомментированные для чего они нужны.

(там написано в приглашении на ввод), или же выбрать бэкап всех почтовых ящиков, написав ALL или all. Далее пользователю предлагается ввести имя почтового ящика, который необходимо бэкапить, причем без указания домена Zimbra.

Если выбрано резервное копирование всех ящиков, то скрипт работает почти так же, как и первый, приведенный выше, за исключением того, что после создания бэкапов каждого ящика, он спросит – а надо ли их архивировать?

Если ящик с указанным именем существует – то запускается процесс резервного копирования этого ящика, с выводом на экран и в лог-файл соответствующей информации. Если был написан конкретный почтовый ящик, то осуществляется проверка его существования в Zimbra. Если указанного ящика не существует – об этом будет сообщено пользователю, и скрипт завершит свою работу.

Если пользователь соглашается – идет проверка отсутствия каталога для складирования архива и далее по списку, как и в первом скрипте. После завершения резервного копирования ящика будет предложено заархивировать копию.

На всякий случай. После завершения архивирования происходит очистка файла со списком ящиков.

В конце выводится информация о времени завершения работы скрипта на экран и в лог-файл.

3) Скрипт Restore.sh:

Как и в предыдущих файлах, сначала – определение переменных с комментариями.

Если указанной даты в бэкапах нет – скрипт завершается, сообщив об этом. Приглашение пользователю выбрать дату резервной копии, которую нужно восстановить.

Чтобы восстановить все ящики нужно написать ALL или all. Если бэкапы на указанную дату существуют – приглашение пользователю ввести имя ящика, который нужно восстановить.

Если выбран параметр ALL, скрипт создает список файлов в папке бэкапа в файл, оповещает о результате создания.

Сначала проверка существования ящика в системе, в случае отсутствия он создается, после чего восстанавливается. Далее идет пошаговое восстановление каждого ящика. О каждой операции выводится информация в лог-файл и на экран.

Проверка существования файла с запрошенным именем. Если выбран конкретный ящик – почти то же самое. Вывод на экран и в лог-файл результата.

Вывод на экран и в лог-файл результата.
Приглашение пользователю согласиться с созданием ящика в случае отсутствия такового в системе. Проверка существования ящика в системе. Вывод на экран и в лог-файл результата.

Вывод на экран и в лог-файл результата.
Восстановление ящика. Создание ящика в случае согласия. Вывод на экран и в лог-файл результата.

Очистка файла со списком ящиков на восстановление.

В конце выводится информация о времени завершения работы скрипта на экран и в лог-файл.

5. По поводу восстановления

Если немного модифицировать данные скрипты, то они вполне подойдут и для перемещения почты с сервера на сервер, просто создав на новом месте ящики со всем содержимым. Так же можно и восстановить работу системы «с нуля», когда по каким-то причинам проще заново поднять сервер Zimbra, чем пытаться оживить старый. Как было написано выше, можно сохранить образ настроенной виртуальной машины, развернув его при необходимости, и залив в него все данные. Тот же алгоритм действий при переезде с одного сервера Zimbra на другой. И не нужно никаких платных утилит типа Zexstras.

6. Заключение

В целом, ничего сложного в написанных мной скриптах нет. Да, в них много условий, потому что я старался предвидеть как можно больше проблем и ошибок в их работе, но я так же постарался комментировать работу скрипта как можно более понятно. Скорее всего, «из коробки» они заработают не для всех. Может быть, кому-то вообще не подойдет такой способ резервного копирования. Но, надеюсь, многим окажутся полезными.

7. P.S.:

Это вторая статья из серии «как я «Zimbra» внедрял». Первая, про внедрение, LDAP-авторизацию и автоматическое создание ящиков для пользователей AD, вот тут.

И еще хочу отметить, что это мой первый опыт скриптования на баше, из-за этого скрипты получились такими громоздкими и «для особо умных», что называется.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть