Это статья-мануал по скрипту резервного копирования, написанному мной. Скрипт написан на python для Linux. Кому интересно прошу под хабракат.
Возможности
- Создание дифференциальных/полных копий папок
- Создание дифференциальных/полных копий с файловой системы BTRFS
- Создание дифференциальных/полных копий LVM томов
- Создание снапшотов BTRFS
- Ротирование бэкапов/снапшотов
- Логгирование хода выполнения резервного копирования
- Отправка email оповещений
- Выполнение скриптов до/после резервного копирования
Установка
В /etc/apt/source.list добавить:
deb http://repo.nixdi.com/ubuntu/ precise soft
И выполнить в терминале:
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 74C7B31B5F4E1715 && apt-get update && apt-get install py4backup
Обновление пакета выполняется командой:
apt-get update && apt-get upgrade py4backup
ИЛИ
Вручную скачать пакет командой:
wget http://repo.nixdi.com/ubuntu/py4backup_latest.deb
и установить его:
dpkg -i ./py4backup_latest.deb
ИЛИ
Для дистрибутивов, отличных от Ubuntu/Debian выполнить:
git clone https://github.com/larrabee/py4backup
И скопировать файлы ddd и py4backup в директорию с бинарными файлами (обычно /usr/bin), файл py4backup_lib.py в директорию библиотек python. Также потребуется поставить зависимости вручную. Необходим python 3.x, btrfs-tools (btrfs-progs), lvm2, rsync. В папке examples/ вы найдете примеры конфигурационных файлов. Их необходимо скопировать в /etc/py4backup/
Настройка
После установки необходимо скопировать конфигурационные файлы из примера. Для этого выполните:
mv /etc/py4backup/py4backup.conf.example /etc/py4backup/py4backup.conf mv /etc/py4backup/jobs.conf.example /etc/py4backup/jobs.conf
И откройте файл py4backup.conf на редактирование текстовым редактором.
Для boolean параметров допустимо использование True/False, yes/no или 1/0.
Отделять параметр от его значения можно символами '=' или ':'.
Каждый параметр должен находится в своей секции. Название секции пишется перед набором параметров в квадратных скобках ('[]')
Порядок следования параметров в секции и секций не важен. Если параметр не указан в конфигурационном файле, то используется стандартное значение.
Пример конфигурационного файла:
[MAIL] send_mail_reports = True login = Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра. passwd = password sendto = Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра. server = mail.test.com port = 25 tls = True [DD] bs = 4M ddd_bs = 4096 ddd_hash = md5 [LOGGING] logpath = /var/log/py4backup.log enable_logging = True log_with_time = True traceback = False command_output = True [OTHER] temp_snap_name = py4backup_temp_snap host_desc = My Description pathenv = /sbin:/usr/sbin
Рассмотрим параметры подробней:
[MAIL]: здесь определяются параметры отправки уведомлений через email.
send_mail_reports: включает/выключает отправку email отчетов после выполнения задания.
login: логин для входа на smtp сервер.
passwd: пароль для входа на smtp сервер.
sendto: получатели уведомления. Можно вписать несколько адресов через пробел.
server: доменное имя или IP адрес smtp сервера.
port: порт smtp сервера.
tls: включает/выключает использование TLS шифрования.
[DD]: здесь указываются параметры создания резервных копий с помощью программ DD и DDD.
bs: размер блока для программы DD (Используется для создания полных копий LVM томов). Можно указывать размер в байтах, килобайтах (k) и мегабайтах (M). Влияет на скорость создания копии. Оптимальное значение- 32M.
ddd_bs: размер блока для программы DDD (Используется для создания дифференциальных копий LVM томов). Можно указывать размер в байтах. Чем больше размер, тем больше места занимает дифференциальная копия, но тем быстрее она создается. Оптимальное значение- 4096.
ddd_hash: алгоритм хеширования блоков. Возможен выбор между md5, crc32 и None. MD5 сильнее нагружает процессор, чем crc32 и занимает больше места, но в случае использования md5 намного меньше шанс коллизий.
None выключает создание чек сумм. Время создания резервной копии, ее размер и нагрузка на процессор минимальны, но в случае повреждения резервной копии вы не будете знать об этом. Не рекомендуется к использованию.
[LOGGING]: настройка ведения журнала заданий.
logpath: путь до журнала. Если вы используете не стандартное размещение журнала не забудьте поменять настройки logrotate.
enable_logging: включает/выключает ведение журнала.
log_with_time: включает/выключает добавление к каждой записи журнала даты и времени.
traceback: включает/выключает добавление traceback'ов в лог при ошибках. Полезно при отладке.
command_output: включает/выключает добавление в лог консольного вывода команд. Полезно при отладке.
[OTHER]: настройки, не вошедшие в другие разделы.
temp_snap_name: имя временных снапшотов. Используется при создании копии LVM томов или папок/файлов на файловой системе BTRFS. Рекомендуется не изменять без необходимости.
host_desc: текстовое описание хоста. Значение этого параметра будет добавлено в файл журнала и email отчет.
pathenv: значение этого параметра будет добавлено к переменной $PATH(если пройдет проверку). Если необходимо добавить несколько папок их необходимо разделить двоеточием (':') Например в Ubuntu для создания копий LVM томов при запуске py4backup через cron необходимо добавить в переменную $PATH папку /sbin. В данном случае путь указывается без последнего слеша (‘/’)
Задания
Общие сведения
Список заданий находится в файле /etc/py4backup/jobs.conf
Пример задания:
[mail-diff] type = file-diff sopath = server:/opt/ snpath = dpath = /mnt/backup_dest/ dayexp = 30 prescript = bash /root/script1.sh postscript = bash /root/script2.sh include = test test2 exclude = tests*
Где:
[xxx]: уникальное имя задания.
type: тип задания. Подробности см ниже.
sopath: источник резервной копии. В типах file-full, file-diff в качестве источника можно указывать удаленные хосты.
snpath: где создать снапшот. Используется только типами btrfs-full, btrfs-diff и btrfs-snap
dpath: куда сохранять резервную копию. В типах btrfs-full, btrfs-diff, file-full, file-diff в качестве назначения можно указывать удаленные хосты.
dayexp: через сколько дней удалять старые резервные копии. Если установить -1 резервные копии не будут удаляться никогда.
prescript: скрипт, выполняющийся перед резервным копированием. Пайпы, конвейер и другие операторы bash не работают. Если требуется выполнять сложные команды сохраняйте их виде скрипта и запускайте его.
postscript: скрипт, выполняющийся после резервного копирования. Остальное аналогично параметру prescript.
include: что включать в резервную копию. Подробности см. в описании типов резервного копирования.
exclude: что исключать из резервной копии. Подробности см. в описании типов резервного копирования.
Внимание! Все пути должны заканчиваться '/'.
Типы резервного копирования
В каждом задании в параметре 'type' указывается тип резервной копии. Этот параметр влияет на схему рез. копирования и на функцию некоторых параметров.
Всего в py4backup есть 7 типов резервного копирования:
- file-full
- file-diff
- btrfs-full
- btrfs-diff
- btrfs-snap
- lvm-full
- lvm-diff
Рассмотрим их поближе.
file-full
Создает резервную копию используя rsync. Создается резервная копия папки, указанной в sopath включая все папки, примонтированные глубже.
Особенности:
В переменной sopath и dpath можно указывать не только локальные папки, но и удаленные хосты. Например:
sopath = Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра..0.1:/home/admin/ или dpath = server:/home/admin. Во втором случае в файле ~/.ssh/config должна быть корректная запись. Используется авторизация по ключам (доп. инфо. см. в wiki вашего дистрибутива).
Нельзя указывать sopath и dpath удаленными хостами одновременно.
Значение указанное в include и exclude передаются rsync в виде опций --include= и --exclude=. Можно указывать несколько значений через пробел.
file-diff
Создает дифференциальную резервную копию от источника (sopath) и последней полной копией, найденной в папке назначения (dpath). Если полная копия не будет найдена выполнение задания завершиться ошибкой.
Список параметров аналогичен типу 'file-full'.
btrfs-full
Данный тип аналогичен типу 'file-full', но перед созданием резервной копии делается снапшот резервируемой директории и копия снимается уже со снапшота.
Для этого типа резервного копирования необходимо указание параметра snpath. В папке, указанной в snpath будет создан временный снапшот исходной папки (sopath). Причем указанный там путь должен находится на одной файловой системе с папкой, указанной в sopath. Обратите внимание, что копируется только содержимое данного subvolume файловой системы. Все примонтированные папки и вложенные subvolume будут проигнорированы. Список остальных параметров аналогичен типу 'file-full'.
btrfs-diff
При этом типе рез. копирования сначала с исходной папки (sopath) снимается снапшот, а затем создается дифференциальная копия от снапшота и последней полной копией, найденной в папке назначения (dpath). Если полная копия не будет найдена выполнение задания завершиться ошибкой.
Так же, как и для типа 'btrfs-full' необходимо, что бы папка для снапшота (snpath) находилась на одной файловой системе с исходной папкой (sopath).
Обратите внимание, что копируется только содержимое данного subvolume файловой системы. Все примонтированные папки и вложенные subvolume будут проигнорированы. Список остальных параметров аналогичен типу 'file-full'
btrfs-snap
Данный тип создает снапшоты от исходной папки, указанной в sopath в папку снапшотов, указанную в snpath.
Для данного типа не работают параметры exclude, include, dpath. Так же, как и для типа 'btrfs-full' необходимо, что бы папка для снапшотов (snpath) находилась на одной файловой системе с исходной папкой (sopath).
Обратите внимание, что копируется только содержимое данного subvolume файловой системы. Все примонтированные папки и вложенные subvolume будут проигнорированы.
lvm-full
Этот тип предназначен для создания полных копий LVM томов. Рассмотрим некоторые особенности данного типа. В параметре sopath указывается путь до Logical Volume Group (VG). Например:
sopath = /dev/main_vg/
По умолчанию скрипт сделает копию всех томов, находящихся в данном VG.
Параметр dpath указывает где сохранять резервную копию. Указывать удаленные хосты в качестве назначения резервной копии нельзя. Для того, что бы сделать копии только нужных томов можно использовать параметры include и exclude.
Параметр exclude указывает какие тома исключить из резервной копии. Кроме того он принимает кодовое слово all, обозначающее, что надо исключить все тома.
Параметр include указывает какие тома нужно включить в резервную копию. Имеет приоритет над exclude. Например:
exclude = all include = mail root
сделает резервную копию только томов mail и root. А следующий пример сделает копию всех томов, кроме тома mail:
exclude = mail
lvm-diff
И последний (для версии 1.5) тип резервного копирования предназначен для создания дифференциальных копий LVM томов.
Скрипт ищет в папке назначения (dpath) последнюю полную резервную копию и если находит, создает дифференциальную копию между ней и снапшотом текущего состояния. В папке назначения при этом появятся 2 файла *-diff.dd и *-diff.ddm Они ОБА необходимы для восстановления.
Все параметры аналогичны типу lvm-full
Запуск
Запустить требуемые задания на выполнение очень просто.
Необходимо указать ключ –jobs (или -j) и после него указать имена необходимых заданий. Например:
py4backup --jobs backup_data backup_home backup_media
Все указанные задания выполнятся последовательно в порядке их следования в параметре --jobs. Также запуск скрипта возможен через cron, но помните, что переменное окружен cron может отличатся от пользовательского и может потребоваться указать пути до утилит rm, dd, rsync, btrfs, lvcreate, lvremove в переменной pathenv в конфигурационном файле.
Восстановление
Вот мы и подошли к самому интересному. Резервное копирование само по себе ничего не стоит, без возможности быстро восстановить резервную копию. В данном разделе я опишу типичные кейсы восстановления из резервных копий, созданных скриптом.
Файловые бэкапы
Написанное ниже относится как к полным, так и дифференциальным резервным копиям, сделанным заданиями типа btrfs-full, btrfs-diff, file-full, file-diff. Восстанавливать резервную копию необходимо rsync с ключами -aAX. Например:
rsync -aAX /mnt/backup/home/2014-06-21-full/ /home/
или
rsync -aAX /mnt/backup/home/2014-06-22-diff/ /home/
В обоих случаях в папке назначения вы получите полную копию данных, готовую к использованию.
Восстановление снапшотов
Снапшоты, создаваемые типом btrfs-snap можно восстанавливать несколькими способами.
- Как файловый бэкап, скопировав данные rsync (слишком долго и не интересно)
- Примонтировав снапшот, вместо папки, которую необходимо восстановить. Этот способ мы и рассмотрим ниже.
По умолчанию снапшоты создаются в режиме только для чтения. Соответственно вы не сможете напрямую писать в этот снапшот. Рассмотрим пример.
BTRFS используется в качестве корневой файловой системы. С помощь скрипта создаются снапшоты папки /home и складываются в /snapshots_home. И вот настал день, когда нам необходимо восстановить папку /home из снапшота.
Первым делом необходимо освободить папку /home (переименовать или удалить ее).
Далее мы выбираем нужный нам снапшот (пусть это будет снапшот, за 2014-06-19) и создаем снапшот от него (да, да, снапшот снапшота):
btrfs subvolume snapshot /snapshots_home/2014-06-19 /home
Таким образом мы во первых сделали наши данные доступными для записи и обезопасили их. Даже когда скрипт согласно ротации удалит снапшот от 2014-06-19 наш свежесозданный снапшот будет цел.
Восстановление полных бэкапов LVM
Тут все совсем просто.
Необходимо создать новый LVM том, размера равного или больше резервной копии и скопировать на него резервную копию с помощью dd.
Пример:
dd if=/backups/2014-06-19-old_volume-full of=/dev/main_vg/new_volume bs=32M
Восстановление дифференциальных бэкапов LVM
Для данного восстановления необходимо воспользоваться утилитой ddd, идущей в комплекте с py4backup.
Для восстановления ей необходимо указать опцию –restore, ключ -s с путем до файла БЕЗ РАСШИРЕНИЯ, ключ -r с указанием места восстановления (блочное устройство или файл). ddd запоминает путь до полной резервной копии, но если она была перемещена необходимо вручную указать ей новый путь. Сделать это можно с помощью ключа -f.
Пример:
В папке /backup находятся резервные копии:
root@virtserver /
И мы хотим восстановить резервную копию за 2014-06-19 на устройство /dev/main_vg/volume Для этого выполним команду:
ddd --restore -s /backup/2014-06-19-volume-diff -r /dev/main_vg/volume
Предположим полная копия была перемещена в папку /backup_old/:
ddd --restore -s /backup/2014-06-19-volume-diff -r /dev/main_vg/volume -f /backup_old/2014-06-18-volume-full
После восстановления ddd выведет список поврежденных блоков с указанием файла, где находится поврежденный блок. Запись full23 указывает на повреждение блока номер 23 в файле полной копии, а запись diff24 на повреждение блока 24 в дифференциальной копии.
Tips & Tricks
Здесь я расскажу о некоторых не очевидных момента и вариантах использования скрипта.
Заключение
Отказ от ответственности: автор скрипта не несет ответственности за действие или бездействие программы, повлекшее потерю или повреждение данных.
В скрипте ЕСТЬ ошибки (в основном мелкие, у меня и на 4 тестовых машинах работает стабильно) и я буду благодарен за багрепорты (особенно с traceback’ами и консольным выводом команд).
Данный мануал актуален для версии 1.5.3.
Связаться со мной можно по email, адрес Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра. или через хабр.
Исходный код на github.
Пакеты в репозитории.
Спасибо за прочтение и буду благодарен за комментарии.