
1. С чего начать
С чего начинается резервное копирование? Планирование. При резервировании любой системы необходимо составить план резервного копирования: что именно, как часто, как долго хранить, хватит ли свободного пространства? Из ответов на эти вопросы вытекает ответ на главный вопрос – чем бэкапить?
Если свободного пространства много – можно хранить целиком виртуальную машину. Делать бэкапы тем же Veeam по расписанию, и не думать о сложностях. Но как по мне, так это расточительство, я привык делать все максимально сжато и, по возможности, экономично. Veeam у меня, конечно же, развернут, но им я делаю резервные копии лишь тех систем, которые либо невозможно, либо проблематично и очень долго разворачивать из резервных копий.
Про скрипты средств управления виртуальной средой просто многозначительно промолчу.
У Zimbra есть инструмент zmmailbox. И, при ближайшем рассмотрении его функционала, я понял, что его мне будет более, чем достаточно. Он умеет резервировать и восстанавливать ящики даже на живой системе. И мне понравилась возможность делать бэкапы критичных почтовых ящиков отдельно от бэкапа всей системы. Таким образом простр��нство, занимаемое резервными копиями, будет ограничено размером заархивированных почтовых ящиков, помноженным на количество дней «глубины бэкапа», а не объемом всей системы, помноженной на то же количество дней. К тому же с бэкапа всей системы, в случае с Zimbra, крайне сложно восстановиться. Гораздо проще скопировать виртуальную машину с помощью Veeam или средств управления виртуальной средой (Hyper-V, ESXI, вписать нужное) сразу после настройки системы, и положить «на полочку», чтобы в критичный момент можно было быстро развернуть почти ничего не весящую ВМ и залить в нее бэкапы ящиков. По-моему, это наименее затратный во всех отношениях сценарий.
2. Исходные данные:
ОС сервера: CentOS 7
По поводу ОС
На самом деле разница между CentOS7 и любой другой системой будет заключаться исключительно в командах серверу на установку пакетов, и, возможно, расположении некоторых файлов. Работа ведется в основном с командлетами Zimbra, так что отличия настройки будет минимальны.
Домен Zimbra: zimbramail.home.local
Имя пользователя и пароль для доступа к расшаренной папке: ZimbraBackUp / 123123
Путь к расшаренной папке: \\BackUpServer1\ZM\
Путь монтирования шары на хосте Zimbra: /mnt/ZM/
3. Настройка
Итак, начнем!
Бэкапы будем писать на сервер под управлением Windows, в расшаренную папку. При желании можно сливать резервные копии куда угодно, но у меня все настроено так, что большинство бэкапов пишутся именно на BackUpServer1.home.local. Так что:
1) Создаем в домене пользователя для доступа к р��сшаренной папке на этом сервере, чтобы можно было смонтировать ее на сервере Zimbramail.home.local. Имя пользователя ZimbraBackUp, пароль, условно, 123123.
2) На сервере BackUpServer1 создаем в хранилище директорию \ZM\, и расшариваем ее, давая права на изменение для пользователя ZimbraBackUp. Путь к шаре будет таким: \\BackUpServer1\ZM\
3) Монтируем шару к серверу Zimbramail.home.local. Чтобы папка монтировалась автоматически, нужно поправить файл /etc/fstab, добавив в него строку:
//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 $MPath ]; then
#Создание каталога хранения долговрочных архивов
echo "Создание каталога хранения долгосроных архивов..."
mkdir -p $MPath
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 $ArchPath -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
fi
#Создание резервных копий каждого ящика из списка
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
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
fi
#Создание резервной копии ящика $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
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 "Очистка файла со споском ящиков..."
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.sh5) Делаем скрипты исполняемыми:
$ chmod 0740 /opt/zimbra/BkUpRestScripts/FullBackUp.sh
$ chmod 0740 /opt/zimbra/BkUpRestScripts/HandBackUp.sh
$ chmod 0740 /opt/zimbra/BkUpRestScripts/Restore.sh6) Рекомендую руками запустить скрипты и проверить, работают ли они, и как они работают.
7) Создать задачу в CRON для ежедневного резервного копирования почтовых ящиков:
10 0 * * * root /opt/zimbra/ BkUpRestScripts/FullBackUp.sh8) Наслаждаться
4. Работа скриптов
На случай, если комментарии в самих скриптах не помогли.
1) Скрипт FullBaclUp.sh:
В начале определяются переменные, какая за что отвечает – все прокомментировано.
Далее следует проверка отсутствия каталога для резервного копирования, если он не существует – создается. Делается вывод в лог-файл и на экран (если запущен руками) о успехе или не успехе создания каталога.
Проверка отсутствия каталога с сегодняшней датой. Если его нет — создается, так же вывод на экран и в лог результата создания каталога.
Запись в файл всех существующих почтовых ящиков Zimbra. Он нужен для последовательного резерварования каждого ящика. Вывод на экран результата выполнения команды.
Создание бэкапа для каждого ящика из полученного списка. С выводом результата выполнения на экран и в лог-файл.
Очистка файла со списком ящиков. Так как с этим файлом работают все 3 скрипта, то целесообразно чистить его после каждого прогона, чтобы не было неожиданностей. Можно чистить его и перед началом работы скрипта, но мне как-то привычнее не хранить лишних данных после выполнения работы, а делать одно и то же до и после работы скрипта – легкая степень шизофрении.
Далее блок по созданию сжатого архива.
Проверка отсутствия каталога хранения архивов, его создание при отсутствии и вывод на экран и в лог результата создания.
Архивирование.
Проверка «а не первое ли сегодня число?». Я предпочитаю долгосрочно хранить бэкапы за 1е числа всех месяцев, мне этого для работы достаточно. Можно и по неделям хранить, но зачастую это избыточно. А вот сверху поставлено условие хранения бэкапов за весь период работы почтового сервера, так что лежать им там веки вечные. Если число – первое, то полученный архив копируется в отдельный каталог “ Mounthly ”. И чтобы его туда скопировать – нужно проверить, нет ли такого каталога, и если нет – создать его, о чем сообщать на экран и в лог-файл.
Далее осуществляется чистка хранилища – удаляются все резервные копии старше 2х недель, а также архивы, старше 61 дня. Результат удаления выводится на экран и в лог-файл.
После чего скрипт пишет время завершения работы в лог-файл и на экран, и завершает свою работу.
Далее следует проверка отсутствия каталога для резервного копирования, если он не существует – создается. Делается вывод в лог-файл и на экран (если запущен руками) о успехе или не успехе создания каталога.
Проверка отсутствия каталога с сегодняшней датой. Если его нет — создается, так же вывод на экран и в лог результата создания каталога.
Запись в файл всех существующих почтовых ящиков Zimbra. Он нужен для последовательного резерварования каждого ящика. Вывод на экран результата выполнения команды.
Создание бэкапа для каждого ящика из полученного списка. С выводом результата выполнения на экран и в лог-файл.
Очистка файла со списком ящиков. Так как с этим файлом работают все 3 скрипта, то целесообразно чистить его после каждого прогона, чтобы не было неожиданностей. Можно чистить его и перед началом работы скрипта, но мне как-то привычнее не хранить лишних данных после выполнения работы, а делать одно и то же до и после работы скрипта – легкая степень шизофрении.
Далее блок по созданию сжатого архива.
Проверка отсутствия каталога хранения архивов, его создание при отсутствии и вывод на экран и в лог результата создания.
Архивирование.
Проверка «а не первое ли сегодня число?». Я предпочитаю долгосрочно хранить бэкапы за 1е числа всех месяцев, мне этого для работы достаточно. Можно и по неделям хранить, но зачастую это избыточно. А вот сверху поставлено условие хранения бэкапов за весь период работы почтового сервера, так что лежать им там веки вечные. Если число – первое, то полученный архив копируется в отдельный каталог “ Mounthly ”. И чтобы его туда скопировать – нужно проверить, нет ли такого каталога, и если нет – создать его, о чем сообщать на экран и в лог-файл.
Далее осуществляется чистка хранилища – удаляются все резервные копии старше 2х недель, а также архивы, старше 61 дня. Результат удаления выводится на экран и в лог-файл.
После чего скрипт пишет время завершения работы в лог-файл и на экран, и завершает свою работу.
2) Скрипт HandBackUp.sh:
В нач��ле так же определяются переменные, так же прокомментированные для чего они нужны.
Далее пользователю предлагается ввести имя почтового ящика, который необходимо бэкапить, причем без указания домена Zimbra. (там написано в приглашении на ввод), или же выбрать бэкап всех почтовых ящиков, написав ALL или all.
Если выбрано резервное копирование всех ящиков, то скрипт работает почти так же, как и первый, приведенный выше, за исключением того, что после создания бэкапов каждого ящика, он спросит – а надо ли их архивировать?
Если был написан конкретный почтовый ящик, то осуществляется проверка его существования в Zimbra. Если ящик с указанным именем существует – то запускается процесс резервного копирования этого ящика, с выводом на экран и в лог-файл соответствующей информации. Если указанного ящика не существует – об этом будет сообщено пользователю, и скрипт завершит свою работу.
После завершения резервного копирования ящика будет предложено заархивировать копию. Если пользователь соглашается – идет проверка отсутствия каталога для складирования архива и далее по списку, как и в первом скрипте.
После завершения архивирования происходит очистка файла со списком ящиков. На всякий случай.
В конце выводится информация о времени завершения работы скрипта на экран и в лог-файл.
Далее пользователю предлагается ввести имя почтового ящика, который необходимо бэкапить, причем без указания домена Zimbra. (там написано в приглашении на ввод), или же выбрать бэкап всех почтовых ящиков, написав ALL или all.
Если выбрано резервное копирование всех ящиков, то скрипт работает почти так же, как и первый, приведенный выше, за исключением того, что после создания бэкапов каждого ящика, он спросит – а надо ли их архивировать?
Если был написан конкретный почтовый ящик, то осуществляется проверка его существования в Zimbra. Если ящик с указанным именем существует – то запускается процесс резервного копирования этого ящика, с выводом на экран и в лог-файл соответствующей информации. Если указанного ящика не существует – об этом будет сообщено пользователю, и скрипт завершит свою работу.
После завершения резервного копирования ящика будет предложено заархивировать копию. Если пользователь соглашается – идет проверка отсутствия каталога для складирования архива и далее по списку, как и в первом скрипте.
После завершения архивирования происходит очистка файла со списком ящиков. На всякий случай.
В конце выводится информация о времени завершения работы скрипта на экран и в лог-файл.
3) Скрипт Restore.sh:
Как и в предыдущих файлах, сначала – определение переменных с комментариями.
Приглашение пользователю выбрать дату резервной копии, которую нужно восстановить. Если указанной даты в бэкапах нет – скрипт завершается, сообщив об этом.
Если бэкапы на указанную дату существуют – приглашение пользователю ввести имя ящика, который нужно восстановить. Чтобы восстановить все ящики нужно написать ALL или all.
Если выбран параметр ALL, скрипт создает список файлов в папке бэкапа в файл, оповещает о результате создания.
Далее идет пошаговое восстановление каждого ящика. Сначала проверка существования ящика в системе, в случае отсутствия он создается, после чего восстанавливается. О каждой операции выводится информация в лог-файл и на экран.
Если выбран конкретный ящик – почти то же самое. Проверка существования файла с запрошенным именем. Вывод на экран и в лог-файл результата.
Проверка существования ящика в системе. Вы��од на экран и в лог-файл результата.
Приглашение пользователю согласиться с созданием ящика в случае отсутствия такового в системе. Вывод на экран и в лог-файл результата.
Создание ящика в случае согласия. Вывод на экран и в лог-файл результата.
Восстановление ящика. Вывод на экран и в лог-файл результата.
Очистка файла со списком ящиков на восстановление.
В конце выводится информация о времени завершения работы скрипта на экран и в лог-файл.
Приглашение пользователю выбрать дату резервной копии, которую нужно восстановить. Если указанной даты в бэкапах нет – скрипт завершается, сообщив об этом.
Если бэкапы на указанную дату существуют – приглашение пользователю ввести имя ящика, который нужно восстановить. Чтобы восстановить все ящики нужно написать ALL или all.
Если выбран параметр ALL, скрипт создает список файлов в папке бэкапа в файл, оповещает о результате создания.
Далее идет пошаговое восстановление каждого ящика. Сначала проверка существования ящика в системе, в случае отсутствия он создается, после чего восстанавливается. О каждой операции выводится информация в лог-файл и на экран.
Если выбран конкретный ящик – почти то же самое. Проверка существования файла с запрошенным именем. Вывод на экран и в лог-файл результата.
Проверка существования ящика в системе. Вы��од на экран и в лог-файл результата.
Приглашение пользователю согласиться с созданием ящика в случае отсутствия такового в системе. Вывод на экран и в лог-файл результата.
Создание ящика в случае согласия. Вывод на экран и в лог-файл результата.
Восстановление ящика. Вывод на экран и в лог-файл результата.
Очистка файла со списком ящиков на восстановление.
В конце выводится информация о времени завершения работы скрипта на экран и в лог-файл.
5. По поводу восстановления
Если немного модифицировать данные скрипты, то они вполне подойдут и для перемещения почты с сервера на сервер, просто создав на новом месте ящики со всем содержимым. Так же можно и восстановить работу системы «с нуля», когда по каким-то причинам проще заново поднять сервер Zimbra, чем пытаться оживить старый. Как было написано выше, можно сохранить образ настроенной виртуальной машины, развернув его при необходимости, и залив в него все данные. Тот же алгоритм действий при переезде с одного сервера Zimbra на другой. И не нужно никаких платных утилит типа Zextras.
6. Заключение
В целом, ничего сложного в написанных мной скриптах нет. Да, в них много условий, потому что я старался предвидеть как можно больше проблем и ошибок в их работе, но я так же постарался комментировать работу скрипта как можно более понятно. Скорее всего, «из коробки» они заработают не для всех. Может быть, кому-то вообще не подойдет такой способ резервного копирования. Но, надеюсь, многим окажутся полезными.
7. P.S.:
Это вторая статья из серии «как я «Zimbra» внедрял». Первая, про внедрение, LDAP-авторизацию и автоматическое создание ящиков для пользователей AD, вот тут.
Третья статья об автоматическом формировании и обновлении списков рассылки на основе групп AD в Zimbra OSE вот тут.
И еще хочу отметить, что это мой первый опыт скриптования на баше, из-за этого скрипты получились такими громоздкими и «для особо умных», что называется.
