Десятимиллионный скрипт резервного копирования
Это статья-мануал по скрипту резервного копирования, написанному мной. Скрипт написан на 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 = login@test.com passwd = password sendto = recipient@test.com 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-snapdpath: куда сохранять резервную копию. В типах 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 = root@192.168.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 / # ls /backup/ 2014–06–18-volume-full 2014–06–19-volume-diff.dd 2014–06–19-volume-diff.ddm И мы хотим восстановить резервную копию за 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 Здесь я расскажу о некоторых не очевидных момента и вариантах использования скрипта.Заключение Отказ от ответственности: автор скрипта не несет ответственности за действие или бездействие программы, повлекшее потерю или повреждение данных.В скрипте ЕСТЬ ошибки и я буду благодарен за багрепорты (особенно с traceback«ами и консольным выводом команд).Данный мануал актуален для версии 1.5.3.Связаться со мной можно по email, адрес larrabee@nixdi.com или через хабр.Исходный код на github.Пакеты в репозитории.Спасибо за прочтение и буду благодарен за комментарии.