SCROLL
Среднее время на прочтение: 5 мин.

Резервное копирование и восстановление почтовых ящиков в Zimbra Collaboration 8.6

В этой статье мы разбирали как развернуть Zimbra Collaboration 8.6 на Ubuntu 14.04 Trusty Tahr. В бесплатной версии почтового сервера нет удобного функционала по бекапу и восстановлению почтовых ящиков. А создание бекапов, есть неотъемлемая часть работы любого системного администратора. Да и наличие бекапа всегда нас спасет в трудную минуту.

 

Создавать бекапы и восстанавливать их же будем посредством bash-скриптов. Создавать и восстанавливать почтовые ящики мы будем на горячую так сказать, без остановки почтового сервера.

 

 

Резервное копирование всех почтовых ящиков

Создаем текстовый файл и делаем его исполняемым:

nano backup_all_mailbox.sh
sudo chmod +x backup_all_mailbox.sh

 

В созданный скрипт вписываем следующее (в параметрах настроек скрипта указываем данные свои):

#!/bin/bash

#####################
# Настройки скрипта #
#####################
# Путь к месту бекапа
Path_backup="/home/jakonda/bkzm"
# Временный файл для работы
Source_list="/home/jakonda/temp"
# Название домена
Domain="jakondo.ru"
# Значение текущей даты
Current_date=$(date +%d-%m-%Y)
# Лог-файл
Log=$Path_backup"/"$Current_date"/log"
echo "#####################################################"
echo "# Резервное копирование всех почтовых ящиков Zimbra #"
echo "#####################################################"
echo ""
echo "Время начала бекапа всех почтовых ящиков - $(date +%T)"
echo "Начало бекапа - $(date +%T)" > $Log
# Запоминаем время начала бекапа
Begin_time=$(date +%s)
echo ""
# Определяем список всех имеющихся почтовых ящиков
echo "Формируем список всех почтовых ящиков для бекапа..."
/opt/zimbra/bin/zmprov -l gaa $Domain > $Source_list
if [ $? -eq 0 ]; then
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
echo "Формирование списка почтовых ящиков успешно выполнено." >> $Log
echo
else
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]"
echo "Формирование списка почтовых ящиков не удалось выполнить. Завершение работы (Неудача)." >> $Log
exit
echo
fi
# Проходимся по всем ящикам в полученном списке и делаем бекап каждого
echo "Выполняем резервное копирование всех почтовых ящиков"
echo "----------------------------------------------------"
mkdir -p $Path_backup/$Current_date/
echo "Создание каталога $Current_date для размешения бекапа." >> $Log
for mailbox in $( cat $Source_list); do
echo "Резервирование почтового ящика - $mailbox"
/opt/zimbra/bin/zmmailbox -z -m $mailbox getRestUrl "//?fmt=tgz" > $Path_backup/$Current_date/$mailbox.tgz
if [ $? -eq 0 ]; then
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
echo "Бекап почтового ящика $mailbox успешен" >> $Log
echo
else
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]"
echo "Бекап почтового ящика $mailbox не удачно" >> $Log
echo
fi
done
# Вычисление времени работы бекапа почтовых ящиков
End_time=$(date +%s)
Elapsed_time=$(expr $End_time - $Begin_time)
Hours=$(($Elapsed_time / 3600))
Elapsed_time=$(($Elapsed_time - $Hours * 3600))
Minutes=$(($Elapsed_time / 60))
Seconds=$(($Elapsed_time - $Minutes * 60))
echo "Затрачено времени на резервное копирование : $Hours час $Minutes минут $Seconds секунд"
echo "Затрачено времени на резервное копирование : $Hours час $Minutes минут $Seconds секунд" >> $Log

 

В ходе выполнения скрипта, сначала формируется список всех почтовых ящиков имеющихся в указанном домене, затем по каждому почтовому ящику создается бекап, в конце создается лог файл. Пример вывода работы скрипта:

#####################################################
# Резервное копирование всех почтовых ящиков Zimbra #
#####################################################
Время начала бекапа всех почтовых ящиков - 05:36:51
Формируем список всех почтовых ящиков для бекапа... [OK]
Выполняем резервное копирование всех почтовых ящиков
----------------------------------------------------
Резервирование почтового ящика - galsync@jakondo.ru [OK]
Резервирование почтового ящика - jakonda1@jakondo.ru [OK]
Резервирование почтового ящика - jakonda2@jakondo.ru [OK]
Затрачено времени на резервное копирование : 0 час 0 минут 22 секунд

 

Лог файл выглядит вот так:

Начало бекапа - 07:50:26
Формирование списка почтовых ящиков успешно выполнено.
Создание каталога 24-01-2017 для размешения бекапа.
Бекап почтового ящика galsync@jakondo.ru успешен
Бекап почтового ящика jakonda1@jakondo.ru успешен
Бекап почтового ящика jakonda2@jakondo.ru успешен
Затрачено времени на резервное копирование : 0 час 0 минут 21 секунд

 

Теперь можно скрипт закидывать в cron и быть спокойным что у нас всегда будет под рукой бекап почтовых ящиков.

 

 

Резервное копирование конкретного почтового ящика

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

nano backup_single_mailbox.sh
sudo chmod +x backup_single_mailbox.sh

 

В созданный скрипт вписываем следующее (в параметрах настроек скрипта указываем данные свои):

#!/bin/bash

#####################
# Настройки скрипта #
#####################
# Путь к месту бекапа
Path_backup="/home/jakonda/bkzm"
# Название домена
Domain="jakondo.ru"
# Значение текущей даты
Current_date=$(date +%d-%m-%Y)
# Лог-файл
Log=$Path_backup"/"$Current_date"/log_single"
echo "################################################"
echo "# Резервное копирование почтового ящика Zimbra #"
echo "################################################"
echo ""
# Запрос ввода имени почтового ящика
read -p "Введите название почтового ящика: " Mail_name
echo "Время начала бекапа почтового ящика ($Mail_name@$Domain) - $(date +%T)"
# Запоминаем время начала бекапа
Begin_time=$(date +%s)
echo ""
# Выполняем бекап указанного почтового ящика
echo "Выполняем резервное копирование почтового ящика $Mail_name@$Domain"
mkdir -p $Path_backup/$Current_date/
echo "Запрос на бекап почтового ящика $Mail_name@$Domain" >> $Log
echo "Начало бекапа - $(date +%T)" >> $Log
/opt/zimbra/bin/zmmailbox -z -m $Mail_name"@"$Domain getRestUrl "//?fmt=tgz" > $Path_backup/$Current_date/$Mail_name"@"$Domain.tgz
if [ $? -eq 0 ]; then
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
echo "Бекап почтового ящика $Mail_name@$Domain успешен" >> $Log
echo
else
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]"
echo "Бекап почтового ящика $Mail_name@$Domain не удачно" >> $Log
# Удаляем неудачный файл
rm $Path_backup/$Current_date/$Mail_name"@"$Domain.tgz
echo
fi
# Вычисление времени работы бекапа почтовых ящиков
End_time=$(date +%s)
echo "Конец бекапа - $(date +%T)" >> $Log
Elapsed_time=$(expr $End_time - $Begin_time)
Hours=$(($Elapsed_time / 3600))
Elapsed_time=$(($Elapsed_time - $Hours * 3600))
Minutes=$(($Elapsed_time / 60))
Seconds=$(($Elapsed_time - $Minutes * 60))
echo "Затрачено времени на резервное копирование : $Hours час $Minutes минут $Seconds секунд"
echo "Затрачено времени на резервное копирование : $Hours час $Minutes минут $Seconds секунд" >> $Log

 

В ходе выполнения скрипта запрашивается у пользователя имя почтового ящика и создается бекап указанного почтового ящика, в конце создается лог файл. Пример вывода работы скрипта:

################################################
# Резервное копирование почтового ящика Zimbra #
################################################
Введите название почтового ящика: jakonda2
Время начала бекапа почтового ящика (jakonda2@jakondo.ru) - 10:00:53
Выполняем резервное копирование почтового ящика jakonda2@jakondo.ru [OK]
Затрачено времени на резервное копирование : 0 час 0 минут 7 секунд

 

Лог файл выглядит вот так:

Запрос на бекап почтового ящика jakonda2@jakondo.ru
Начало бекапа - 10:00:53
Бекап почтового ящика jakonda2@jakondo.ru успешен
Конец бекапа - 10:01:00
Затрачено времени на резервное копирование : 0 час 0 минут 7 секунд

 

Мы получили удобный в работе скрипт по созданию бекапа отдельно взятого почтового ящика.

 

 

Восстановление почтового ящика из резервной копии

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

 

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

 

Создаем текстовый файл и делаем его исполняемым:

nano restore_single_mailbox.sh
sudo chmod +x restore_single_mailbox.sh

 

В созданный скрипт вписываем следующее (в параметрах настроек скрипта указываем данные свои):

#!/bin/bash

#####################
# Настройки скрипта #
#####################
# Путь где хранятся бекапы
Path="/home/jakonda/bkzm"
# Название домена
Domain="jakondo.ru"
echo "#########################################"
echo "# Восстановление почтового ящика Zimbra #"
echo "#########################################"
echo ""
# Запрос даты, за какое число нужно восстановить бекап
read -p "Введите дату за какое число восстановить из бекапа (прим. 01-01-1985): " Date
# Проверим наличия бекапов за указанную дату
if ! [ -d $Path/$Date ]; then
echo 'Нет бекапов на указанную дату... Завершаем работу скрипта.'
exit
fi
# Лог-файл
Log=$Path"/"$Date"/log_single_restore"
# Запрос имени почтового ящика, который нужно восстановить
read -p "Введите имя почтового ящика (без указания домена): " MailBox
# Проверяем есть ли бекап почтового ящика с указанным именем
MailBox=$MailBox"@"$Domain
if ! [ -f $Path/$Date/$MailBox.tgz ]; then
echo 'Нет бекапа указанного почтового ящика... Завершаем работу скрипта.'
exit
fi
echo "Время начала восстановление почтового ящика ($MailBox) - $(date +%T)"
# Запоминаем время начала восстановления
Begin_time=$(date +%s)
echo "" >> $Log
echo "Начало процесса восстановления - $(date +%T)" >> $Log
echo ""
# Проверяем существует ли восстонавливаемый почтовый ящик
echo "Проверяем существует ли почтовый ящик $MailBox в Zimbra"
Result=$(/opt/zimbra/bin/zmprov getMailboxInfo $MailBox)
if [ $? -eq 0 ]; then
echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]"
echo "Почтовый ящик $MailBox существует, восстанавливаем его..." >> $Log
echo
echo "Почтовый ящик $MailBox существует, восстанавливаем его..."
echo
else
echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
echo "Почтовый ящик $MailBox не существует, создаем его..." >> $Log
echo
echo "Почтовый ящик $MailBox не существует, создаем его..."
echo
# Запрос имени почтового ящика, который нужно восстановить
read -p "Введите ФИО владельца почтового ящика $MailBox (Иванов Иван Иванович): " FIO
Result=$(/opt/zimbra/bin/zmprov ca $MailBox Aa1234567 displayName "$FIO")
if [ $? -eq 0 ]; then
echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]"
echo "Почтовый ящик $MailBox успешно создан, продолжаем восстановление его..." >> $Log
echo
echo "Почтовый ящик $MailBox успешно создан, продолжаем восстановление его..."
echo
else
echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
echo "Почтовый ящик $MailBox не удалось создать, завершаем работу скрипта." >> $Log
echo
echo "Почтовый ящик $MailBox не удалось создать, завершаем работу скрипта."
echo
exit
fi
fi
# Выполняем восстановление указанного почтового ящика
echo "Восстановление почтового ящика $MailBox"
Result=$(/opt/zimbra/bin/zmmailbox -z -m $MailBox -t 0 postRestURL «//?fmt=tgz&resolve=replace» $Path/$Date/$MailBox.tgz)
if [ $? -eq 0 ]; then
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
echo "Восстановление почтового ящика $MailBox успешено" >> $Log
echo
else
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]"
echo "Восстановление почтового ящика $MailBox не удачно" >> $Log
echo
fi
# Вычисление времени работы бекапа почтовых ящиков
End_time=$(date +%s)
echo "Конец восстановления - $(date +%T)" >> $Log
Elapsed_time=$(expr $End_time - $Begin_time)
Hours=$(($Elapsed_time / 3600))
Elapsed_time=$(($Elapsed_time - $Hours * 3600))
Minutes=$(($Elapsed_time / 60))
Seconds=$(($Elapsed_time - $Minutes * 60))
echo "Затрачено времени на восстановление : $Hours час $Minutes минут $Seconds секунд"
echo "Затрачено времени на восстановление : $Hours час $Minutes минут $Seconds секунд" >> $Log

 

В ходе выполнения скрипта запрашивается сперва дата бекапа, затем имя почтового аккаунта (без указания домена), следом идет проверка существования аккаунта в Zimbra (в случае его отсутствия, он создается) и производится восстановление почтового ящика, в конце создается лог файл. Пример вывода работы скрипта (при условии что аккаунт в Zimbra отсутствует):

#########################################
# Восстановление почтового ящика Zimbra #
#########################################
Введите дату за какое число восстановить из бекапа (прим. 01-01-1985): 24-01-2017
Введите имя почтового ящика (без указания домена): jakonda_test
Время начала восстановление почтового ящика (jakonda_test@jakondo.ru) - 03:18:18
Проверяем существует ли почтовый ящик jakonda_test@jakondo.ru в Zimbra [FAIL]
ERROR: account.NO_SUCH_ACCOUNT (no such account: jakonda_test@jakondo.ru)
Почтовый ящик jakonda_test@jakondo.ru не существует, создаем его...
Введите ФИО владельца почтового ящика jakonda_test@jakondo.ru (Иванов Иван Иванович): Иванов Иван Иванович 
Почтовый ящик jakonda_test@jakondo.ru успешно создан, продолжаем восстановление его... [OK]
Восстановление почтового ящика jakonda_test@jakondo.ru [OK]
Затрачено времени на восстановление : 0 час 0 минут 43 секунд

 

Лог файл выглядит вот так:

Начало процесса восстановления - 03:18:18
Почтовый ящик jakonda_test@jakondo.ru не существует, создаем его...
Почтовый ящик jakonda_test@jakondo.ru успешно создан, продолжаем восстановление его...
Восстановление почтового ящика jakonda_test@jakondo.ru успешено
Конец восстановления - 03:19:01
Затрачено времени на восстановление : 0 час 0 минут 43 секунд

 

Вот такими способами можно легко делать резервные копии почтовых ящиков и с той же легкостью восстанавливать их из резервной копии.

Обсуждение

30 комментариев
  • Скрипт на создание отрабатывает, создает бэкап. После удалая ящик, запускаю скрипт на восстановление удаленного ящика, но выскакивает ошибка ./restore_single_mailbox.sh: line 72: /home/…./bkzm/01-12-2023/domain.ru.tgz: Permission denied. В админке при этом создается пустой почтовый ящик. Zimbra 8.8.15 , подскажите куда копать

    • Это ответ на комментарий евгений

      права на файл бекапа проверьте, ругается на это явно — Permission denied

  • При восстановление выдает такую ошибку:
    ERROR: zclient.IO_ERROR (Read timed out) (cause: java.net.SocketTimeoutException Read timed out)
    В чем может быть причина?

  • В скрипте восстановления есть 2 ошибки:
    1. Переменную Path_backup нужно исправить на Path
    2. Если архив под восстановление больше 4 Гб , то спустя минут 15 выводит ошибку ERROR: zclient.IO_ERROR (Read timed out) (cause: java.net.SocketTimeoutException Read timed out)
    Решение , добавить в скрипте восстановление параметр -t 0 , чтобы получилось
    Result=$(/opt/zimbra/bin/zmmailbox -z -m $MailBox -t 0 postRestURL «//?fmt=tgz&resolve=replace» $Path/$Date/$MailBox.tgz)

    Автору спасибо большое за скрипты

    • Это ответ на комментарий Egor

      здесь тоже ошибка.
      «//?fmt=tgz&resolve=replace»

      вот так будет правильней:
      «//?fmt=tgz&resolve=replace»

      😉

  • У вас был опыт восстановления из бекапа почтового ящика более 1 гигабайта?
    Столкнулся с проблемой что зимбра рабивает инбокс на несколько инбоксов с индексом и пользователь ругается, что все разбилось по папкам.

  • не совсем правильно выразился наверное, восстановление архивов почты по списку ящиков. не одного почтового ящика, а нескольких ..

    • Это ответ на комментарий gr

      Такого скприта я не писал, т.к. не видел в нем надобности для себя. Но все возможно, восстанавливать к примеру из списка..

  • А есть вариант восстановления списка ящиков?

  • Ув. roman@kovenya.ru, я не могу разместить ваши посты. Рад что вы модернизировали скрипт под свои нужны, но данный блог про мои труды.

    • Это ответ на комментарий Жаконда

      Печаль. Надо пилить свой блог =) Тем не менее присмотритесь к моим решениям, возможно найдёте для себя что-то интересное.

      • Это ответ на комментарий orangefruit

        Спасибо, мой вариант скрипта писался строго под мои нужны и он меня более чем устраивает на данный момент 😉 У меня нет сложностей расширить его в случае надобности.

  • После обновления с 8.6 на 8.7 при выполнении /opt/zimbra/bin/zmmailbox -z -m $Mail_name»@»$Domain происходит ошибка

    ERROR: zclient.IO_ERROR (invoke sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target, server: localhost) (cause: javax.net.ssl.SSLHandshakeException sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target)

    Что может быть, не подскажите?

    • Это ответ на комментарий Pavel

      Судя по ошибке проблема в сертификате. Попробуйте его пересоздать.

      • Это ответ на комментарий Жаконда

        /opt/zimbra/bin/zmcertmgr deploycrt пересоздал сертификаты заново — и все заработало.
        Спасибо за скрипт

  • Добрый день! Если я правильно понял, выше привеленные сценарии делают полный бекап всех/одного я щика соответственно. Не расматривали ли возможность инкрементного бекапа если полная копия уже существует? И еще один вопрос: сколько по времени занимает создание полной резервной копии, ну например 150 ящиков?

    • Это ответ на комментарий Алексей

      Добрый день ! Нет, инкрементный бекап не рассматривал, там в разы гемор добавляется и не факт что вообще получится скриптом делать его..

      По затраты времени создания бекапа, тут все индивидуально, все зависит сколько весит каждый ящик, если все 150 ящиков весят в среднем по 10Мб, то бекап их будет очень быстрый.. соответственно если больше то и время будет увеличиваться.

      • Это ответ на комментарий Жаконда

        >>если больше то и время будет увеличиваться.
        Вот в том то и дело. Главным требованием руководства при создании сервера было сохранение всей почты за весь цикл жизни почтового домена, домен существует года с 10-11 точно ни знаю, сервер с 13, большая часть ящиков мигрировала от хостера. В итоге имеем порядка 20 ящиков объемом ~15-50 гб, всего порядка 150 ящиков в двух доменах на одном сервере. Теперь и не знаю что со всем этим делать.

        • Это ответ на комментарий Алексей

          Сейчас это все резервируется rsync-ом, но есть траблы с востановлением — занимает достаточно много времени.

        • Это ответ на комментарий Алексей

          Такие как у вас объемы ящиков, уверен никакой инструмент не будет сохранять быстро..

  • Спасибо, отличный скрипт. А стоит ли останавливать сервис зимбры перед бекапом ящиков? Что-бы ничего не изменилось в момент бекапа.

    • Это ответ на комментарий Костя

      Пожалуйста ! Ну бекап обычно делается ночью, а ночью обычно не работают, хотя могут и работать 🙂 Ну при желании конечно можно и останавливать зимбру, тут дело дальше как кому удобней

      • Это ответ на комментарий Жаконда

        >>а ночью обычно не работают,
        Ну я бы так так не сказал, у нас например комерческие рассылки в ночь отрабатывают, в принципе как и многих.

  • У Вас реализованы готовые скрипты для бэкапирования отдельных почтовых ящиков zimba.
    Большое Вам Спасибо! Очень помогло!

      • Это ответ на комментарий Жаконда

        Спасибо за скрипт! А как бэкапите саму зимбру? Чтобы в случаее выхода сервера из строя можно было восстановить сервер

        • Это ответ на комментарий Василий

          Добрый день ! Пользуйтесь на здоровье ! Саму зимбру никак не бекаплю, нет смысла, т.к. разворачивается она быстро, главное при переносе или пере установке это бекап ящиков, списков рассылки и само собой аккаунтов.

        • Это ответ на комментарий Жаконда

          а списки рассылок и аккаунты ты тоже этим скриптом бэкапишь?