Утилита резервного копирования rdiff-backup
Утилита резервного копирования rdiff-backup
написана на Python, обладает большой гибкостью и довольно простая в использовании. Может работать как локально, так и поверх rsync/ssh, предоставляя возможность оптимально использовать каналы передачи данных в случае удалённых бэкапов. Можно выделить следующие основные возможности:
- Инкрементное копирование. Позволяет восстановить любой файл, удаленный хоть год назад, при том что резервное копирование выполняется, скажем, два раза в день.
- Сохранение всей информации о файлах. Восстанавливая файл из бэкапа, мы получаем его в таком виде, в каком он был на момент добавления, включая timestamp, права доступа, владельцев и т.п. При этом утилита корректно ведет себя в различных типах файловых систем.
- Эффективное использование дискового пространства. Используя алгоритм rsync, утилита сохраняет только изменения файлов, а не все файлы целиком. БД весом в пару десятков гигабайт не будет каждый раз копироваться целиком, а только изменения.
- Прозрачное хранение данных. Утилита хранит бэкапы в точно таком же виде, в каком файлы находились на диске, не прибегая к хитроумным форматам. Например, чтобы восстановить последний бэкап, можно просто скопировать нужные файлы обратно на место.
- Автоматическое определение типов файловых систем позволяет утилите избавить от полного понимания всех тонкостей её настройки в зависимости от типа используемой файловой и операционной системы.
Установка утилиты
В современных Linux-дистрибутивах rdiff-backup
имеется в репозиториях:
$ sudo apt install rdiff-backup
Синтаксис
$ rdiff-backup [опции] источник получатель
Локальное резервное копирование
Сперва рассмотрим самый простой способ запуска утилиты:
$ rdiff-backup /var/www/example.com/ /backup/www/example.com/
В качестве получателя необходимо указывать либо пустой, либо несуществующий каталог. Регулировать разговорчивость утилиты можно при помощи опции -v
(или --verbosity
). Опция может принимать значения от 0 до 9 (по умолчанию оно равно 3).
Удалённое резервное копирование
На удалённой системе должна быть установлена rdiff-backup
и работать ssh-сервер. Выполним с веб-сервера example.com
резервное копирование файлов на backup-сервер backup.com
— из каталога /var/www/example.com
в каталог /backup/www/example.com
:
$ rdiff-backup -v 5 /var/www/example.com/ evgeniy@backup.com::/backup/www/example.com/
Эта команда установит соединение с сервером backup.com
при помощи ssh, запустит на нем rdiff-backup
в режиме сервера (опция --server
) и выполнит передачу файлов.
То же самое будет работать и в обратном направлении. Выполним с backup-сервера backup.com
резервное копирование файлов веб-сервера example.com
— из каталога /var/www/example.com
в каталог /backup/www/example.com
:
$ rdiff-backup -v 5 evgeniy@example.com::/var/www/example.com/ /backup/www/example.com/
Если ssh-сервер работает на нестандартном порту, нужно использовать опцию --remote-schema
, которая по умолчанию имеет значение
ssh -C %s rdiff-backup --server
Где вместо %s
подставляется username@server.com
. Чтобы использовать нестандартный порт, нужно изменить значение этой опции:
$ rdiff-backup -v 5 --remote-schema 'ssh -p 2222 -C %s rdiff-backup --server' \ > evgeniy@example.com::/var/www/example.com/ /backup/www/example.com/
Получение информации о результатах бэкапа
Обычно многословный вывод требуется в период отладки и написания сценариев. Для мониторинга результатов работы утилиты желательно иметь лишь краткую сводку. Для этого rdiff-backup
предлагает отдельную опцию --print-statistics
.
$ rdiff-backup --print-statistics /var/www/example.com/ /backup/www/example.com/ --------------[ Session statistics ]-------------- StartTime 1598082207.00 (Sat Aug 22 10:43:27 2020) EndTime 1598082208.71 (Sat Aug 22 10:43:28 2020) ElapsedTime 1.71 (1.71 seconds) SourceFiles 10 SourceFileSize 8123909 (7.75 MB) MirrorFiles 10 MirrorFileSize 8123909 (7.75 MB) NewFiles 0 NewFileSize 0 (0 bytes) DeletedFiles 0 DeletedFileSize 0 (0 bytes) ChangedFiles 0 ChangedSourceSize 0 (0 bytes) ChangedMirrorSize 0 (0 bytes) IncrementFiles 0 IncrementFileSize 0 (0 bytes) TotalDestinationSizeChange 0 (0 bytes) Errors 0 --------------------------------------------------
Исключение из бэкапа файлов и каталогов
Часто в копируемых каталогах попадаются файлы, размер которых весьма немаленький, а смысла включать их в бэкап нет. Используя опцию --exclude
, можно исключать отдельные файлы и каталоги.
$ rdiff-backup --exclude /var/www/example.com/cache \ > evgeniy@example.com::/var/www/example.com/ /backup/www/example.com/
Иногда проще указать, что надо включить в бэкап, чем перечислять, что из него надо исключить:
$ rdiff-backup --include /usr/local --include /var --exclude '**' \ > / evgeniy@example.com::/var/host/example.com/
Эта команда создаст резервную копию каталогов /usr/local
и /var
. И при этом исключит из резервной копии все остальные каталоги.
rdiff-backup
позволяет использовать шаблоны: **
эквивалентно любому пути, а *
— любому пути без завершающего слеша.
Восстановление из резервной копии
Восстановить локальную копию можно при помощи команды cp
. Если резервая копия была создана командой
$ rdiff-backup /var/www/example.com/ /backup/www/example.com/
То восстановить ее можно при помощи команды
$ cp -a /backup/www/example.com/* /var/www/example.com/
При этом будет скопирован каталог rdiff-backup-data
со служебной информацией утилиты. Так что его надо удалить:
$ rm -r /var/www/example.com/rdiff-backup-data/
Разумеется, утилита rdiff-backup
умеет и сама восстанавливать файлы с помощью опции -r
(или --restore-as-of
). Например, восстановим утраченные файлы веб-сервера из последней версии архива (now
) на backup-сервере:
$ rdiff-backup -r now evgeniy@backup.com::/backup/www/example.com/ /var/www/example.com/
$ rdiff-backup -r 10D \ # восстановить из архива, который был сделан 10 дней назад > evgeniy@backup.com::/backup/www/example.com/ /var/www/example.com/
Посмотреть историю создания бэкапов и потом выбрать нужный можно с помощью опции -l
(или --list-increments
):
$ rdiff-backup -l evgeniy@backup.com::/backup/www/example.com/ Found 3 increments: increments.2020-08-21T15:55:57+03:00.dir Fri Aug 21 15:55:57 2020 increments.2020-08-21T16:55:57+03:00.dir Fri Aug 21 16:55:57 2020 # версия для восстановления increments.2020-08-21T17:55:57+03:00.dir Fri Aug 21 17:55:57 2020 Current mirror: Fri Aug 21 18:55:57 2020 # последняя версия архива
$ rdiff-backup -r 2B \ # восстановить из архива две версии назад > evgeniy@backup.com::/backup/www/example.com/ /var/www/example.com/
Можно восстанавливать не весь архив, а отдельные каталоги или файлы. Смотрим существующие версии файла и восстанавливаем нужную:
$ rdiff-backup --list-increments \ # посмотреть существующие версии файла > evgeniy@backup.com::/backup/www/example.com/index.php Found 3 increments: index.php.2020-08-21T15:55:53+03:00.missing Fri Aug 21 15:55:53 2020 index.php.2020-08-21T16:55:53+03:00.diff.gz Fri Aug 21 16:55:53 2020 index.php.2020-08-21T17:55:53+03:00.diff.gz Fri Aug 21 17:55:53 2020 # версия для восстановления Current mirror: Fri Aug 21 18:55:53 2020 # последняя версия файла
$ rdiff-backup --force -r 1B \ # восстановить файл на одну версию назад > evgeniy@backup.com::/backup/www/example.com/index.php /var/www/example.com/index.php
Если файл в приемнике уже существует, rdiff-backup
откажется его заменять и предложит использовать опцию --force
для принудительной перезаписи существующего файла:
Fatal Error: Restore target /var/www/example.com/index.php already exists, specify --force to overwrite.
Удаление старых файлов
Для удаления бекапов старше определенного времени используется опция --remove-older-than
.
Удалим с backup-сервера бэкапы старше трех недель:
$ rdiff-backup --remove-older-than 3W evgeniy@backup.com::/backup/www/example.com/
Удалим с backup-сервера бэкапы старше одного месяца:
$ rdiff-backup --remove-older-than 1M evgeniy@backup.com::/backup/www/example.com/
Оставляем на backup-сервере только 10 последних версий:
$ rdiff-backup --remove-older-than 10B evgeniy@backup.com::/backup/www/example.com/
s
, m
, h
, D
, W
, M
и Y
— секунды, минуты, часы, дни, недели, месяцы и годы.
Прочие опции утилиты
Опция --list-at-time время
показывает список файлов в архиве, которые существовали в указанный момент времени. Если указан путь к каталогу в архиве, будут показаны только файлы в этом каталоге.
$ rdiff-backup --list-at-time 7D /backup/www/example.com/
Опция --list-changed-since время
показывает список файлов, которые были изменены с указанного момента времени. Если указан путь к каталогу в архиве, будут показаны только файлы в этом каталоге.
$ rdiff-backup --list-changed-since 1h /backup/www/example.com/
Опция --compare-at-time время
позволяет сравнить текущее состояние каталога-источника с архивом на указанный момент времени. Позволяет проверить актуальность резервной копии. Сравниваются метаданные файлов — этот способ утилита использует и при резервном копировании.
--compare
является сокращением для --compare-at-time now
, т.е. сравнивает текущее состояние каталога-источника с последней версией архива.
Опция --compare-hash-at-time время
позволяет сравнить текущее состояние каталога-источника с архивом на указанный момент времени. Для каждого файла источника вычисляется контрольная сумма SHA1 и сравнивается с метаданными в архиве на указанный момент времени.
--compare-hash
является сокращением для --compare-hash-at-time now
, т.е. сравнивает текущее состояние каталога-источника с последней версией архива.
Опция --compare-full-at-time время
позволяет сравнить текущее состояние каталога-источника с архивом на указанный момент времени. Но при этом производится побайтовое сравнение файлов в источнике с файлами в архиве. Это самый медленный, но наиболее полный вариант сравнения.
--compare-full
является сокращением для --compare-full-at-time now
, т.е. сравнивает текущее состояние каталога-источника с последней версией архива.
Опция --server
обеспечивает переход в режим сервера утилиты на удаленном компьютере. Эту опцию нельзя указывать напрямую, она исключительно для того, чтобы утилита на локальном компьютере могла управлять утилитой на удаленном компьютере.
Опция --test-server
позволяет проверить работу утилиты в режиме сервера на удаленном компьютере.
Скрипт резервного копирования
Допустим, у нас есть веб-сервер www.example.com
и сервер для хранения резервных копий backup.example.com
. Бэкап-сервер с некоторой периодичностью будет выполянять копирование файлов из каталога /var/www/example.com/
веб-сервера в локальный каталог /backup/www/example.com/
.
#!/bin/bash
# ---------------------------------------------------------------
# Скрипт решает две задачи:
# 1. Выполняет резервное копирование файлов с сервера $REMOTE_SRV
# из директории $REMOTE_DIR в локальную директорию $BACKUP_DIR
# 2. Отправляет письмо на почту админу о результатах копирования
# ---------------------------------------------------------------
# путь к утилите бэкапа rdiff-backup на локальном сервере
BACKUP_RDF='/usr/bin/rdiff-backup'
# локальная директория, где будем хранить резервные копии
BACKUP_DIR='/backup/www/example.com/'
# сколько резервных копий хранить (0 — без ограничений)
BACKUP_CNT=0
# ip-адрес или домен удаленного сервера для ssh-соединения
REMOTE_SRV='www.example.com'
# имя пользователя на удаленном сервере для ssh-соединения
REMOTE_USR='sergey'
# дополнительные опции для ssh — порт или путь к файлу ключа
REMOTE_SSH='-p 2222 -i /home/sergey/.ssh/id_rsa'
# путь к утилите бэкапа rdiff-backup на удаленном сервере
REMOTE_RDF='/usr/bin/rdiff-backup'
# директория на удаленном сервере, которую будем бэкапить
REMOTE_DIR='/var/www/example.com/'
# программа для отправки почты через внешний SMTP-сервер
MAIL_SSMTP='/usr/sbin/ssmtp'
# адрес почты админа, куда будем отправлять отчет о бэкапе
MAIL_ADMIN='sergey-ivanov@yandex.ru'
# отправлять отчет всегда (1) или только в случае ошибок (0)
MAIL_ERROR=1
# директория, где размещен скрипт резервного копирования
current=$(dirname $(realpath $0))
# сохраняем результат прошлого резервного копирования
if [[ -f "$current/last-backup.stat" ]]; then
cp "$current/last-backup.stat" "$current/prev-backup.stat"
fi
# -------------------------------------------
# Первая задача: резервное копирование файлов
# -------------------------------------------
# значение опции --remote-schema, чтобы передать утитите rdiff-backup
remote_schema="ssh $REMOTE_SSH -C %s $REMOTE_RDF --server"
# команда резервного копирования с использованием утилиты rdiff-backup
command="$BACKUP_RDF --print-statistics --remote-schema '$remote_schema' $REMOTE_USR@$REMOTE_SRV::$REMOTE_DIR $BACKUP_DIR"
# выполянем резервное копирование и сохраняем результат в файл
bash -c "$command &> $current/last-backup.stat"
# результат резервного копирования, потребуется несколько раз ниже
success=$?
# если резервное копирование прошло успешно — удаляем старые бэкапы
if [[ $success -eq 0 && $BACKUP_CNT -ne 0 ]]; then
echo '' >> "$current/last-backup.stat"
echo '--------------[ Remove old backups ]--------------' >> "$current/last-backup.stat"
bash -c "$BACKUP_RDF --remove-older-than ${BACKUP_CNT}B $BACKUP_DIR &>> $current/last-backup.stat"
echo '--------------------------------------------------' >> "$current/last-backup.stat"
fi
# если резервное копирование прошло успешно, а отправлять отчет
# нужно только в случае ошибок — то больше ничего не делаем
if [[ $success -eq 0 && $MAIL_ERROR -eq 0 ]]; then
exit 0
fi
# ---------------------------------------
# Вторая задача: отправка отчета на почту
# ---------------------------------------
# создаем файл message.txt с заголовком письма и телом письма
if [[ $success -eq 0 ]]; then
subject='Backup success'
else
subject='Backup errors'
fi
echo "Subject: $subject" > "$current/mail.text"
echo '' >> "$current/mail.text"
cat "$current/last-backup.stat" >> "$current/mail.text"
# отправляем письмо администратору через внешний SMTP-сервер
bash -c "$MAIL_SSMTP $MAIL_ADMIN < $current/mail.text"
rm "$current/mail.text"
exit $success
Осталось только добавить регламентное задание, чтобы скрипт запускался в 8:00 и 20:00
# crontab -e
0 8,20 * * * /root/backup/backup.bash
Пример отчета, который будет приходить на почту
--------------[ Session statistics ]-------------- StartTime 1598277415.00 (Mon Aug 24 16:56:55 2020) EndTime 1598277416.01 (Mon Aug 24 16:56:56 2020) ElapsedTime 1.01 (1.01 seconds) SourceFiles 10 SourceFileSize 8123909 (7.75 MB) MirrorFiles 10 MirrorFileSize 8123909 (7.75 MB) NewFiles 0 NewFileSize 0 (0 bytes) DeletedFiles 0 DeletedFileSize 0 (0 bytes) ChangedFiles 0 ChangedSourceSize 0 (0 bytes) ChangedMirrorSize 0 (0 bytes) IncrementFiles 0 IncrementFileSize 0 (0 bytes) TotalDestinationSizeChange 0 (0 bytes) Errors 0 -------------------------------------------------- --------------[ Remove old backups ]-------------- No increments older than Mon Aug 24 16:49:49 2020 found, exiting. --------------------------------------------------
Поиск: Linux • Python • SSH • Ubuntu • rdiff-backup • Бэкап • Резервная копия