Версия для печати
Среда, 28 февраля 2018 12:50

Резервное копирование и восстановление Zimbra Collaboration

Автор
Оцените материал
(2 голосов)

Мы успешно установили и ввели в эксплуатацию почтовый сервер Zimbra вместо MS Exchange. Все хорошо работает и управляется. Но встает вопрос с резервным копированием почтовых ящиков и учетных записей сервера. В безплатной версии Zimbra Collaboration отсутствует встроенный механизм резервного копирования и восстановления. Он присутствует только в платной версии. Либо придется закупать дополнительный продукт, "заточенный" именно под эту версию почтового сервера. Ключевое слово - "покупать". Не все компании готовы к платным версиям (а зря), тем полее в свете темы "импортозамещения". Приходится обходится самописными скриптами. Но, к сожалению, они будут плохо работать на больших и очень больших системах в основном из-за длительного времени выполнения бэкапа и, в меньшей степени, из-за отсутствия GUI. В этой статье будут представлены несколько скриптов, позволяющих сделать полную резервную копию почтовых ящиков сервера и восстанавливать эти ящики и учетные записи из архива.

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

  1. Создаем новый файл в удобном каталоге и делаем его исполняемым:
    touch /opt/zimbra/scripts/backup_mbox.sh
    chmod +x /opt/zimbra/scripts/backup_mbox.sh
    
  2. Созданный файл наполняем содержимом:
    #!/bin/bash
    
    #####################
    # Настройки скрипта #
    #####################
    # Путь к месту бекапа
    M_Path_backup="/opt/zimbra/backup"
    # Временный файл для работы
    Source_list="/opt/zimbra/backup/temp"
    # Глубина хранения архива в днях
    Old_date=4
    # Название домена
    Domain="имя_домена.ru"
    # Значение текущей даты
    Current_date=$(date +%d-%m-%Y)
    Path_backup=$M_Path_backup"/"$Domain
    Log=$Path_backup"/"$Current_date"/log"
    echo "###################################################"
    echo "#      Проверяем присутствие лог файла            #"
    if [[ ! -e $Log ]]; then
      mkdir -p $Path_backup/$Current_date/
      touch $Log
      echo "Создание каталога $Current_date для размешения бекапа." > $Log
    elif [[ ! -d $Log ]]; then
      echo "Лог файл за $Current_date присутствует" > $Log
    fi
    echo "###################################################"
    # Удаляем файлы старше ХХХ дней
    echo "###################################################"
    echo "#         Удаляем архивы старше $Old_date дней            #"
    DELETE_DAY_FILES=`/usr/bin/find $Path_backup -type f -mtime +$Old_date`
    
      if [[ ! -z $DELETE_DAY_FILES ]]; then
        echo "Найдены файлы старше $Old_date дней" >> $Log
        echo "$DELETE_DAY_FILES" >> $Log
    
        # Удаление пустых и скрытых директорий
        del_empty_dir(){
          find $Path_backup -empty -type d -delete >/dev/null 2>&1
          find $Path_backup -type d -name ".*" -exec rm -rf '{}' \; >/dev/null 2>&1
          echo "Пустые папки удалены!" >> $Log
        }
    
        # Удаление пустых и скрытых файлов
        del_empty_files(){
          find $Path_backup -empty -type f -delete >/dev/null 2>&1
          find $Path_backup -type f -name ".*" -exec rm -rf '{}' \; >/dev/null 2>&1
          echo "Пустые и скрытые файлы удалены!" >> $Log
        }
    
        # Попытка удаления всего
        del(){
        # find $Path_backup $Old_date -exec rm -rf '{}' \; >/dev/null 2>&1
        # find $Path_backup/* -mtime +$Old_date -print0 | xargs -0 rm -rf 2>&1 >/dev/null
        find $Path_backup -mtime +$Old_date -print0 | xargs -0 rm -rf 2>&1 >/dev/null
        }
    
        del
        del_empty_files
        del_empty_dir
        echo "#          Файлы старше $Old_date удалены                 #"
        echo "###################################################"
      else
        echo "#          Файлов старше $Old_date не найдено             #"
        echo "###################################################"
      fi
    echo "$Current_date $(date +%T) : Завершение удаления старых файлов" >> $Log
    echo ""
    ####
    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 "----------------------------------------------------"
    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
    
    Переменные M_Path_backup, Old_date и Domain выстовляем в зависимости от своих требований.
  3. Что делает скрипт:
    • В первую очередь идет проверка на наличие старых файлов. Глубина хранения в днях задается переменной Old_date . Файлы и каталоги в архиве старше установленного количества дней будут удаляться.
    • Затем формируется список всех почтовых ящиков в указанном домене (переменная Domain)
    • Затем по каждому почтовому ящику создается бекап и помещается в папку M_Path_backup плюс имя домена плюс текущая дата.
    • Все выполняемые действия заносятся в лог-файл, находящейся в той же папке.
  4. Теперь этот скрипт можно запускать по таймеру (например каждый день или раз в неденлю). При каждом запуске создается полная резервная копия всех почтовых ящиков. Разностное копирование не предусмотрено (да и вряд ли его можно реализовать скриптами)

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

Создаем скрипт следующего содержания:

#!/bin/bash

#####################
# Настройки скрипта #
#####################
# Путь к месту бекапа
M_Path_backup="/opt/zimbra/backup"
# Вводим имя почтового домена
read -p "Домен пользователя: " Domain
# Путь к хронению бэкапа заданного домена
Path_backup=$M_Path_backup"/"$Domain
# Значение текущей даты
Current_date=$(date +%d-%m-%Y)
# Лог-файл
Log=$Path_backup"/"$Current_date"/log_single"
echo "###################################################"
echo "#      Проверяем присутствие лог файла            #"
if [[ ! -e $Log ]]; then
  mkdir -p $Path_backup/$Current_date/
  touch $Log
  echo "Создание каталога $Current_date для размешения бекапа." > $Log
elif [[ ! -d $Log ]]; then
  echo "Лог файл за $Current_date присутствует" >> $Log
fi
echo "###################################################"
echo ""
echo "################################################"
echo "# Резервное копирование почтового ящика Zimbra #"
echo "################################################"
echo ""
# Запрос ввода имени почтового ящика
read -p "Введите название почтового ящика: " Mail_name
echo "Время начала бекапа почтового ящика ($Mail_name@$Domain) - $(date +%T)"
# Запоминаем время начала бекапа
Begin_time=$(date +%s)
echo ""
# Выполняем бекап указанного почтового ящика
echo "Выполняем резервное копирование почтового ящика $Mail_name@$Domain"
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

Описание работы скрипта:

  1. Необходимо задать M_Path_backup. Это переменная обозначает каталог, куда будет сохранен архив почтового ящика пользователя.
  2. Затем скрипт выдаст запрос на имя домена, в котором находится почтовый ящик пользователя.
  3. Затем выдается запрос на имя пользователя, для которого необходимо создать резервную копию. Имя необходимо вводить БЕЗ второй части почтового адреса.
  4. После ввода всех данных начинается процесс создания резервной копии почтового ящика пользователя. Бекап помещается в папку, заданную переменной M_Path_backup плюс имя домена плюс текущая дата и имеет название имя_пользователя@имя_домена
  5. Все действия заносятся в лог-файл, находящийся в той же папке.

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

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

#!/bin/bash

#####################
# Настройки скрипта #
#####################
# Путь где хранятся бекапы
M_Path="/opt/zimbra/backup"
# Название домена
#Domain="jakondo.ru"
# Вводим имя почтового домена
read -p "Домен пользователя: " Domain
# Путь к хронению бэкапа заданного домена
Path=$M_Path"/"$Domain
if ! [ -d $Path ]; then
  echo "Резервных копий для домена $Domain не найдено. Завершение работы"
  exit
fi
echo "#########################################"
echo "# Восстановление почтового ящика Zimbra #"
echo "#########################################"
echo ""
# Запрос даты, за какое число нужно восстановить бекап
read -p "Введите дату за какое число восстановить из бекапа (прим. 01-01-1985): " Date
# Проверим наличия бекапов за указанную дату
if ! [ -d $Path/$Date ]; then
echo 'Нет бекапов на указанную дату... Завершаем работу скрипта.'
exit
fi
# Лог-файл
Log=$Path"/"$Date"/log_single"
echo "###################################################"
echo "#      Проверяем присутствие лог файла            #"
if [[ ! -e $Log ]]; then
  touch $Log
  echo "Создание лог-файла в каталоге $Date." >> $Log
  echo "###################################################"
elif [[ ! -d $Log ]]; then
  echo "Лог файл за $Date присутствует" >> $Log
  echo "###################################################"
fi
# Запрос имени почтового ящика, который нужно восстановить
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 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

В скрипте указываем в переменной M_Path путь, где лежат резервные копии.

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

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

Соответственно скрипты самые пройстейшие. Не восстанавливается членство в группах рассылки, не отслеживается запрет на присутствие в GAL, не заполняются поля "Фамилия", "Имя" и т.д. После восстановления требуется корректировка всех свойств пользователя. Но на то оно и безплатное, что бы "жизнь медом не казалась".

Архивирование всех учетных записей всех доменов на сервере.

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

Для создания учетной записи из командной строки используется команда zmprov с соответствующими параметрами:

zmprov ca   парамерт1 "значение1" параметр2 "значение2" ... параметрN "значениеN"

Что бы точно узнать название параметра, зайдите в админку, откройте редактирование учетной записи и кликните мышкой на нужном вам параметре.

Для выгрузки всех учетных записей почтового сервера создаем скрипт backup_users.sh со следующим содержимым:

#!/bin/bash

zmprov=/opt/zimbra/bin/zmprov
password=jJYdg3d7aisdhDwed # Временный пароль, установите свой, но сложный!

echo "#!/bin/bash";
echo "";
for mbox in `$zmprov -l gaa | egrep -v 'avir|galsync|spam|ham|virus'`; do

    # Получаем параметры почтового ящика
    cn=`$zmprov -l ga $mbox cn | grep cn: | sed 's/cn: //'`
    givenName=`$zmprov -l ga $mbox givenName | grep givenName: | sed 's/givenName: //'`
    displayName=`$zmprov -l ga $mbox displayName | grep displayName: | sed 's/displayName: //'`
    zimbraPrefFromDisplay=`$zmprov -l ga $mbox zimbraPrefFromDisplay | grep zimbraPrefFromDisplay: | sed 's/zimbraPrefFromDisplay: //'`
    zimbraAuthLdapExternalDn=`$zmprov -l ga $mbox zimbraAuthLdapExternalDn | grep zimbraAuthLdapExternalDn: | sed 's/zimbraAuthLdapExternalDn: //'`
    userPassword=`$zmprov -l ga $mbox userPassword | grep userPassword | sed 's/userPassword: //'`

    # Формируем строку для создания почтового ящика
    echo "$zmprov ca $mbox $password userPassword \"$userPassword\" cn \"$cn\" displayName \"$displayName\" givenName \"$givenName\" zimbraPrefFromDisplay \"$zimbraPrefFromDisplay\" zimbraAuthLdapExternalDn \"$zimbraAuthLdapExternalDn\"";

    # Получаем список альясов для почтового ящика
    for alias in `$zmprov ga $mbox | grep zimbraMailAlias | sed 's/zimbraMailAlias: //'`; do
        echo "$zmprov aaa $mbox $alias";
    done

    echo "";

done

Если выполнить этот скрипт в формате:

backup_users.sh > /opt/zimbra/backup/restore_users.sh

то в каталоге /opt/zimbra/backup получим файл restore_users.sh, содержащий команды для восстановления учетных записей пользователей.

Для загрузки учетных записей пользователей Zimbra необходимо выполнить полученный скрипт. Результатом выполнения будет список id учетных записей пользователей:

f856788b-ceb0-4d88-92de-1f8065bede1d
b32de718-6e1c-4a54-aca7-117c23de31e1
c7990605-ff7f-4005-8ad4-c2a742b88afa
...

ВАЖНО: перед выполнением скрипта требуется создать необходимые домены.

Архивирование всех почтовых ящиков пользователей.

Кроме учетных записей необходимо так же архивировать (переносить) содержимое почтовых ящиков. Для этого создаем скрипт backup_mbox.sh с содержимым:

#!/bin/bash

zmbox=/opt/zimbra/bin/zmmailbox
zmprov=/opt/zimbra/bin/zmprov

backup=/opt/zimbra/backup # Папка, куда выгружать архивы ящиков 

echo "$(date +%T): -- Begin dump mailboxes -- ";

for mbox in `$zmprov -l gaa | egrep -v 'avir|galsync|spam|ham|virus'`; do

    echo "$(date +%T): Begin dump $mbox";
    $zmbox -z -m $mbox -t 0 getRestURL "//?fmt=tgz" > $backup/$mbox.tgz
    echo "$(date +%T): End dump $mbox";
    echo "";

done

echo "$(date +%T): -- End dump mailboxes -- ";

В результате выполнения этого скрипта в папке /opt/zimbra/backup появятся архивы почтовых ящиков

Импорт (восстановление) почтовых ящиков.

Для того чтобы загрузить содержимое (письма, календари, задачи) в существующие учетные записи, используется команда:

/opt/zimbra/bin/zmmailbox -z -m Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. postRestURL "//?fmt=tgz&resolve=reset" /tmp/Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Создаем файл restore_mboxes.sh с содержимым:

#!/bin/bash

zmbox=/opt/zimbra/bin/zmmailbox
zmprov=/opt/zimbra/bin/zmprov

backup=/opt/zimbra/backup # Папка, где хратся выгружанные архивы ящиков 

echo "$(date +%T): -- Begin restore mailboxes -- ";

for mbox in `$zmprov -l gaa | egrep -v 'avir|galsync|spam|ham|virus'`; do

    echo "$(date +%T): Begin restoring files from $mbox";
    $zmbox -z -m $mbox -t 0 postRestURL "//?fmt=tgz&resolve=reset" $backup/$mbox.tgz
    echo "$(date +%T): End restoring files from $mbox";
    echo "";

done

echo "$(date +%T): -- End restore mailboxes -- ";

Скрипт загрузит содержимое архивов из папки /opt/zimbra/backup в соответствующие учетные записи электронной почты.

ВАЖНО: Необходимо убедиться, что лимиты всех почтовых ящиков позволяют загрузить все сообщения из архива.

Данные скрипты переносят не все параметры. Если каких-то параметров не хватает, то в скрипт backup_users.sh необходимо их добавить.

Получить значение параметров можно командой:

/opt/zimbra/bin/zmprov -l ga Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Перенос (архивация) данных Policyd

Плагин Policyd для обработки статистики и правил. Свои данные он хранит в базе sqlite3. Для архивации достаточно скопировать файл базы данных:

# su - zimbra -c "zmcbpolicydctl stop"
# cp /opt/zimbra/data/cbpolicyd/db/cbpolicyd.sqlitedb /opt/zimbra/backup/cbpolicyd.sqlitedb
# su - zimbra -c "zmcbpolicydctl start"

Для восстановления базы данных выполняем:

# su - zimbra -c "zmcbpolicydctl stop"
# cp /opt/zimbra/backup/cbpolicyd.sqlitedb /opt/zimbra/data/cbpolicyd/db/cbpolicyd.sqlitedb 
# su - zimbra -c "zmcbpolicydctl start"

Дополнительная информация

Прочитано 16445 раз Последнее изменение Четверг, 01 марта 2018 12:36
Андрей Иванов

Последнее от Андрей Иванов

Авторизуйтесь, чтобы получить возможность оставлять комментарии