Устроившись на новую работу, я получил в своё владение работающий настроенный сервер Zimbra версии 8.8.15_GA_3847. Работает этот сервер на виртуальной машине, и бэкапирование делается двумя методами:
1. бэкапится сама виртуальная машина
2.1. бэкапятся почтовые ящики всех пользователей раз в неделю
2.2. бэкапятся почтовые ящики некоторых избранных пользователей по будням.
Про бэкап виртуальной машины всё понятно. А вот бэкапы почтовых ящиков делаются скриптами. Предыдущий системный администратор, скорее всего, скрипты взял от сюда:
https://habr.com/ru/post/439728/
Но я их немного причесал под себя, сделав маленькие доработки.
Итак, по будням, каждый вечер запускается вот такой скрипт:
#!/bin/bash # В этом скрипте Зимбра выгружает ящики на локальный диск, не сжимая. В обычный tar. # Потом ящики сжимаются через pbzip2 и копируются в /mnt/mailbox_bkp/Arch-day. # Выгружаются только ящики, заданные в файле /root/Backup_scripts/MBoxesList PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin" #Куда положить бэкап Path="/mnt/mailbox_bkp/Backups" #Куда положить архив бэкапа ArchPath="/mnt/mailbox_bkp/Arch-day" #Список ящиков MBoxes="/root/Backup_scripts/MBoxesList" #Текущая дата CDate=$(date +%d-%m-%Y) #Куда писать логи log="/mnt/mailbox_bkp/BackUpLog.txt" #Начало работы скрипта echo -en echo -en "day BackUp selected MailBoxes started `date '+%d.%m.%y'` in $(date +%T)\n" >> $log #Очистка локального каталога от предыдущих выгрузок echo -en "Clear catalog $Path\n" >> $log rm -Rf $Path/* #Проверка несуществования каталога для резервного копирования 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 #создание резервных копий каждого ящика из списка for MailBox in $( cat $MBoxes); do echo "Создание резервной копии ящика $MailBox..." /opt/zimbra/bin/zmmailbox -z -m $MailBox getRestUrl "//?fmt=tar" > $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 #Создание архива и работа с архивами #Проверка несуществования каталога для архивирвоания 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 используя сжатие pbzip2 tar -C $Path/ -cf $ArchPath/$CDate.tar --use-compress-prog=pbzip2 $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 #Удаление старых архивов бэкапов (старше 2 недель) echo "Удаление старых архивов резервных копий (старше 2 недель)..." find $ArchPath -type f -mtime +14 -delete 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 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 `date '+%d.%m.%y'` in $(date +%T)\n" >> $log echo -en "_____________________________________________\n" >> $log
Скачать можно тут:
https://disk.yandex.ru/d/pNwWhgSYZr3A-w
В нём нужно лишь под себя поправить переменные:
#Куда положить бэкап
Path=
#Куда положить архив бэкапа
ArchPath=
#Список ящиков
MBoxes=
#Куда писать логи
log=
В файл со списком ящиков записаны нужные адреса в каждой отдельной строчке:
ivanov@mydomain.ru
petrov@mydomain.ru
utkin@mydomain.ru
popov@mydomain.ru
sidorov@mydomain.ru
kuznecov@mydomain.ru
и т.д.
По субботам запускается скрипт, бэкапящий все ящики заданного домена:
#!/bin/bash # В этом скрипте Зимбра выгружает ящики на локальный диск, не сжимая. В обычный tar. # Потом ящики сжимаются через pbzip2 и копируются в /mnt/mailbox_bkp/Arch-week. PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin" #Куда положить бэкап Path="/mnt/mailbox_bkp/Backups" #Куда положить архив бэкапа ArchPath="/mnt/mailbox_bkp/Arch-week" #Название домена Zimbra ZDomain="mydomain.ru" #Список ящиков MBoxes="/mnt/mailbox_bkp/MBoxesList" #Текущая дата CDate=$(date +%d-%m-%Y) #Куда писать логи log="/mnt/mailbox_bkp/BackUpLog.txt" #Начало работы скрипта echo -en echo -en "BackUp ALL MailBoxes started `date '+%d.%m.%y'` in $(date +%T)\n" >> $log #Очистка локального каталога от предыдущих выгрузок echo -en "Clear catalog $Path\n" >> $log rm -Rf $Path/* #Проверка несуществования каталога для резервного копирования 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=tar" > $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 используя сжатие pbzip2 tar -C $Path/ -cf $ArchPath/$CDate.tar --use-compress-prog=pbzip2 $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 #Удаление старых архивов бэкапов (старше месяца) echo "Удаление старых архивов резервных копий (старше месяца)..." find $ArchPath -type f -mtime +32 -delete 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 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 `date '+%d.%m.%y'` in $(date +%T)\n" >> $log echo -en "_____________________________________________\n" >> $log
Скачать можно здесь же:
https://disk.yandex.ru/d/pNwWhgSYZr3A-w
И в нём также надо изменить следующие переменные под себя:
#Куда положить бэкап
Path=
#Куда положить архив бэкапа
ArchPath=
#Название домена Zimbra
ZDomain=
#Список ящиков
MBoxes=
#Куда писать логи
log=
Для работы этих двух скриптов требуется пакет pbzip2.
Собственно, у меня эти оба скрипта используют один и тот же файл для лога и один и тот же каталог для выгрузки ящиков. Но сжатые архивы с выгрузкой ящиков кладут в разные каталоги:
Здесь лежат выгрузки почтовых ящиков:
Также есть скрипт восстановления почты из ранее сделанной выгрузки. Вот он:
#!/bin/bash #Где лежат бэкапы Path="/mnt/mailbox_bkp/Backups" #Название домена Zimbra ZDomain="mydomain.ru" #Список ящиков MBoxes="/mnt/mailbox_bkp/MBoxesList" #Куда писать логи log="/mnt/mailbox_bkp/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=tar&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=tar&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
Скачать снова здесь:
https://disk.yandex.ru/d/pNwWhgSYZr3A-w
Вкратце опишу, как им пользоваться. Для начала, надо в нём поправить переменные под себя:
#Где лежат бэкапы
Path=
#Название домена Zimbra
ZDomain=
#Список ящиков
MBoxes=
#Куда писать логи
log=
Допустим, хочу восстановить какой-нибудь старый ящик, который давно удалили, и о котором вспомнили уже спустя время. Сначала надо достать выгрузки почтовых ящиков из общего архива и положить их в каталог из переменной Path. У меня это каталог /mnt/mailbox_bkp/Backups. Общий архив лежит в каталоге /mnt/mailbox_bkp/Arch-day. Делаю это командой:
tar -xvf /mnt/mailbox_bkp/Arch-day/08-09-2022.tar --directory /mnt/mailbox_bkp/Backups
Получу вот такой результат:
Если не получится распаковать сразу через tar, то можно попробовать разжать файл с помощью самой pbzip2, команда будет примерно такая:
pbzip2 -dk -p4 < /mnt/mailbox_bkp/Arch-day/08-09-2022.tar > /mnt/mailbox_bkp/backup.tar
Что разжать: /mnt/mailbox_bkp/Arch-day/08-09-2022.tar
Получаемый расжатый файл: /mnt/mailbox_bkp/backup.tar
-p4 – задействовать 4 потока процессора.
После этого уже распаковать разжатый файл через tar:
tar -xvf /mnt/mailbox_bkp/backup.tar --directory /mnt/mailbox_bkp/Backups
Далее уже можно запускать скрипт восстановления почтового ящика. Скрипт сначала попросит ввести дату резервной копии, которую надо восстановить. У меня это будет 08-09-2022. Если каталога с указанной датой не обнаружится, то скрипт завершит работу. А если каталог с такой датой присутствует, то скрипт спросит, какой ящик восстановить, либо попросит написать ALL для восстановления всех ящиков, которые найдёт в каталоге 08-09-2022.
Собственно, эти бэкап-скрипты можно переделать, чтобы общий архив делался обычным gzip или bzip2 и не заморачиваться с pbzip2, но тогда будет ощутимый проигрыш по времени, ведь, в отличие от gzip и bzip2, pbzip2 использует многопоточность.
Система работает на CentOS 7, но и на других Линуксах эти скрипты должны нормально работать.
Донаты принимаются на кошельки:
Yoomoney:
4100118091867315
Карта Т-Банк (бывший Тиньков):
2200 7017 2612 2077
Карта Альфа-Банк:
2200 1539 1357 2013