UMGUM.COM (лучше) 

Bacula purging ( Автоматизируем удаление устаревших "томов" резервных копий в системе централизованного резервного копирования "Bacula". )

6 ноября 2018  (обновлено 22 января 2019)

OS: "Linux Debian 7/8/9 (Wheezy/Jessie/Stretch)".
Application: "Bacula Director 5.2/7.4".

Система резервного копирования "Bacula" принципиально не обладает функционалом автоматического удаления "томов" резервных копий. Изначально предполагается, что хранение реализовано на магнитных лентах "стримеров", которые заменяются в соответствии с расписанием и перезаписываются - но не удаляются. Вручную можно изменить расписание задания резервного копирования, с усечением количества "томов" (сопоставленных с кассетой магнитной ленты) и высвобождением невостребованных, после чего зачистить сведения о таковых - но файлы это не удаляет.

Задача: в связи с переходом на методику резервного копирования по принципу "одно задание - один том" организовать автоматизированное удаление "томов" резервных копий, срок хранения который превысил указанный в настройках задания резервного копирования "Bacula".


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

# vi /etc/bacula/client.d/example.net.conf

....
Job {
  Name = "example.net"
  ....

  # Подключаем конфигурацию для автоматизации зачистки устаревших резервных копий
  # (это включение должно быть одним из последних в описании задания)
  @/etc/bacula/includes/purge.conf
}

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

# vi /etc/bacula/includes/purge.conf

# Запускаем скрипт зачистки устаревших томов после каждого исполнения задания
RunScript {
  RunsWhen = After; RunsOnFailure = no; RunsOnClient = no;
  Command = "/etc/bacula/scripts/purge-vol.sh %n"
}

Логика работы скрипта "purge-vol.sh" будет опираться на подаваемое ему единственным параметром имя задания резервного копирования, от которого мы изначально договорились строить систему именований "томов" резервных копий:

1. Посредством утилиты "bconsole" ищем пул указанного задания резервного копирования и выясняем срок хранения его томов.
2. На основании полученного параметра от текущей вычисляем дату, ранее которой тома будут считаться устаревшими.
3. Посредством утилиты "bconsole" запрашиваем список имён томов, последняя запись в которые была ранее вычисленного порога.
4. Утилите "bconsole" отправляем указания удалить сведения об устаревших томах и их содержимое, по списку.
5. Файлы устаревших томов удаляем из файловой системы, по списку.

Пишем скрипт на привычном мне языке "Bash":

# vi /etc/bacula/scripts/purge-vol.sh && chmod ug+x /etc/bacula/scripts/purge-vol.sh

#!/bin/bash

STORAGE="/mnt"
LOG="/var/log/bacula/purge-vol.log"
JOB=${1}

# Проверяем корректность вводных данных
[ ! "${1}" ] && { echo "Не указано наименование задачи резервного копирования. Операция прервана."; exit 1; }
CHECK=`echo -e "show job=${JOB}\nexit" | bconsole | grep -i -E "^Job:[[:space:]]+name=${JOB}.*Enabled=1"`
if [ -z "${CHECK}" ] ; then
  echo "Не обнаружена разрешённая к исполнению задача резервного копирования \"${JOB}\". Операция прервана."; exit 1;
fi

# Вычленяем значение параметра срока хранения резервных копий в "пуле" (в секундах)
VOLRETENTION=`echo -e "sqlquery\nselect VolRetention from Pool where Name = 'pool-${JOB}' limit 1;\n.\nexit" | bconsole | grep '^|' | grep -i -v 'VolRetention' | sed -e 's/[ ]*|[ ]*//g' | sed -e '/^[ \t]*$/d' | sed -e 's/,//g'`

# Проверяем успешность получения срока хранения резервных копий "пула" задания
# (во избежание грубейших ошибок примем за минимально допустимый срок хранения в один месяц)
if [ ! -z "${VOLRETENTION}" ] && [ "${VOLRETENTION}" -gt "2678400" ] ; then

  # Вычисляем дату, ранее которой резервная копия будет считаться устаревшей
  DATECUT=`date --date="${VOLRETENTION} seconds ago" '+%Y-%m-%d'`

  # Запрашиваем перечень устаревших "томов", последняя запись в которые была ранее установленного лимита
  DELETELIST=`echo -e "sqlquery\nselect VolumeName from Media where VolumeName like '${JOB}%' and LastWritten < '${DATECUT}' order by VolumeName;\n.\nexit" | bconsole | grep '^|' | grep -i -v ' VolumeName ' | sed -e 's/[ ]*|[ ]*//g' | sed -e '/^[ \t]*$/d'`

  # Обрабатываем список "томов" на удаление
  if [ ! -z "${DELETELIST}" ] ; then

    # Записываем в журнал событий отметку о начале проведения процедуры и далее о ресурсах
    echo >> "${LOG}"
    echo "$(date +"%Y-%m-%d %H:%M:%S") deleted obsolete volumes:" | tee -a "${LOG}"

    # Отправляем "Bacula" указание удалить сведения об указанных "томах" и их содержимое
    echo -e "${DELETELIST}" | xargs -I {} echo "purge yes volume={}" | bconsole > /dev/null 2>&1
    echo -e "${DELETELIST}" | xargs -I {} echo "delete yes volume={}" | bconsole > /dev/null 2>&1

    # Элементарно ищем совпадения по имени тома во всех системах хранения и удаляем файлы "томов" непосредственно с файловой системы
    for VOLUME in ${DELETELIST} ; do
      FULLNAME=$(find "${STORAGE}/" -type f -iname "${VOLUME}" -exec echo {} \; -quit)
      if [ ! -z "${FULLNAME}" ] && [ -f "${FULLNAME}" ] ; then

        # Перед удалением выводим в STDOUT и журнал событий сведения о полном имени и размере целевых файлов
        ls -lah "${FULLNAME}" | awk '{print "  Deleted: " $9 " ("$5")"}' | tee -a "${LOG}"
        rm -f "${FULLNAME}"
      fi
    done

  fi

else
  echo "Не удалось выяснить срок хранения резервных копий по задаче \"${JOB}\", или таковой не выходит за установленный предел. Операция прервана."; exit 1;
fi

exit ${?}

Ограничиваем доступ, профилактически сразу ко всем конфигурациям сервиса "Bacula":

# chown -R bacula:bacula /etc/bacula
# chmod -R o-rwx /etc/bacula

На этом всё. Учитывая то, что Bash-скрипт запускается на исполнение в контексте пользователя "bacula", каких-то дополнительных действий аутентификации при обращении к утилите "bconsole" и файловым ресурсам сервиса "Bacula" не требуется.

Есть смысл поглядывать в журнал событий "/var/log/bacula/purge-vol.log" - там будут записи об удалённых файлах, с указанием их размера, или сообщения об ошибках. Усечение и архивирование разросшихся файлов журнала мы наладили ранее, в соответствие с инструкцией по установке сервера "Bacula".


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )