Статей на эту тему много, к примеру:
- http://wiki.archlinux.org/index.php/Rsync
- http://www.scrounge.org/linux/rsync.html
- http://main.linuxfocus.org/Russian/March2004/article326.shtml
Но нигде не нашел внятного объяснения как сохранять права доступа, группу и владельца, особенно, если удаленный сервер (backup-сервер) работает не от пользователя root.
В общем, постановка задачи:
- инкрементный бекап
- клиент-сервер
- сохранять права доступа, владельца и группу
- сохранять только указанные директории, представлять возможность исключения по паттерну, делать исключения в исключениях :)
- выполнение каких-то операций пред выполнением резервирования
Настройка backup-сервера
Тут все достаточно просто, должны быть установлены пакеты openssh, rsync и их зависимости, openssh должен быть настроен и запущен.
Далее, создаем пользователя под которым будут храниться резервные копии, пусть это будет backup:
adduser backup
отвечаем на все вопросы, вводим пароль (он потребуется только для передачи ключей, но лучше его запомнить).
После чего, в его домашнем каталоге создаем подкаталоги lock
и files
:
mkdir lock file
Затем создаем там же, в домашнем каталоге, файл rsyncd.conf с примерно таким содержимым:
# малость системной информации, подробнее 'man rsyncd.conf'
use chroot = no
max connections = 4
syslog facility = local5
pid file = /home/backup/lock/rsyncd.pid
lock file = /home/backup/lock/rsyncd.lock
[backup]
comment = Backup area
# хранить информацию о правах, владельце и группе в цифровом виде, если не нужно - поставьте no
numeric ids = yes
# эта опция позволяет хранить информацию о правах, владельце, группе в xattr, об этом далее
fake super = yes
# путь к корню, где будут храниться копии
path = /home/backup/files
# по умолчанию, все модули - read only, нам же нужно писать
read only = no
Комментарии по тексту, думаю остальное избыточно.
Теперь ремарка… об этих самых xattr: Я столкнулся с тем, что при попытке записи, выдавалось сообщение об ошибке, и эти самые атрибуты не писались, гугл ответа не дал. Поставил пакет, зовется attr, который нужен для управления расширенными атрибутами файлов. Вдумчивое чтение man 5 attr
дало следующее:
Currently, support for extended attributes is implemented on Linux by the ext2, ext3, ext4, XFS, JFS and reiserfs filesystems.
А, как следствие, вдумчивое чтение ‘man mount’ дало информацию о параметре монтирования user_xattr. У меня файловая система ext4, там этот атрибут по-умолчанию выключен, для сохранения информации о владельце/группе нужно его включить. Поэтому в /etc/fstab для нужной файловой системы после defaults добавил user_xattr, получилось примерно следующее:
UUID=780ae01a-6fe2-416f-baa2-0d700cd9574f /home ext4 defaults,user_xattr 0 1
По сути, это все, что относится к серверной настройке, после потребуется только создания своего индивидуального подкаталога для каждого резервируемого хоста внутри ‘files’, я рекомендую создавать эти каталоги по имени хоста (вывода команды hostname). Пока создадим там каталог host1
Резервируемый хост
Тут нужно набросать скриптик и несколько конфигурационных файлов прописать его в cron для регулярного выполнения:
- backup.sh - сам скрипт, понимает 3 аргумента:
- backup - выполняет резервирование
- list - показывает содержимое бекапа на сервере
- restore <что> <куда> - восстанавливает данные из резервной копии
- backup.conf - конфиг, что бы можно было оперативно размножить по разным хостам
- backup.list - список файлов и директорий подлежащих резервированию
- backup.exclude - список паттернов для исключения из резервирования (man rsync)
- backup.include - писок исключений (отменяет некоторые паттерны в exclude, смотреть man rsync)
- backup_cron - небольщой скрипт для выполнения планировщиком, я его положил в /etc/cron.hourly/, добавив префик zz_, что бы выполнялся последним.
- hook.d/ - директория со скриптами, которые выполняется перед выполнением резервирования
Итак, сами скрипты.
-
backup.sh
#!/bin/bash # ### Скрипт для инкрементного бекапа при помощи rsync+ssh # с сохранением прав/владельца файла в расширенных # атрибутов (требуется монтирование файловой системы на # которую будет производится резервирование с опцией user_xattr) # # Version: 20100512.1 # # «THE BEER-WARE LICENSE» (Revision 42): # hatred@inbox.ru wrote this file. As long as you retain # this notice you can do whatever you want with this stuff. # If we meet some day, and you think this stuff is worth it, # you can buy me a beer in return. Alexander 'hatred' Drozdoff # source backup.conf [ -z "$host" ] && host=`hostname` exclude=backup.exclude include=backup.include backups=backup.list DAY=$(env LANG=C date +"%F_%H") do_hooks() { for pkg in hook.d/* do [ -x $pkg ] && ./$pkg done } do_backup() { is_incr_exists=$(ssh $ssh_user@$host "stat files/$dest/incr/$DAY > /dev/null 2>&1 && echo yes || echo no") if [ "$is_incr_exists" == "yes" ]; then ssh $ssh_user@$host rm -rf files/$dest/incr/$DAY fi do_hooks rsync -av -R <br/> -e "ssh -l $ssh_user" <br/> --fake-super <br/> --delete <br/> --delete-excluded <br/> --inplace <br/> --backup <br/> --backup-dir=/$dest/incr/$DAY <br/> --exclude-from=$exclude <br/> --include-from=$include <br/> $(cat $backups) <br/> $host::backup/$dest/full/ } do_list() { rsync -v -e "ssh -l $ssh_user" $host::backup/$dest/$1 } do_restore() { rsync -av -e "ssh -l $ssh_user" --super --safe-links $host::backup/$dest/$1 $2 } do_help() { cat << _EOF_ Use: $0 <backup|list|restore> [SRC] [DEST] _EOF_ } action=$1 shift case $action in backup) do_backup ;; list) do_list $@ ;; restore) do_restore $@ ;; *) do_help ;; esac
-
backup.conf
# пользователь на бекап сервере, под которым хранятся резервные копии (того что мы создавали) ssh_user=backup # IP или HOST backup-сервера host=backup.server # Имя поддиректории в files на backup-сервере для хранения данных конкретного хоста dest=host
-
backup.list, просто список директорий и файлов, главное, если хотите сохранять саму директорию, а не его содержимое, не ставьте в конце “/”, т.е. вместо “/etc/” пишите “/etc”. примерное содержимое:
/etc /home /root /var/backup
-
backup.exclude, список паттернов (man rsync). Обратите внимание, испключается последний элемент, т.е.
/var/cache/*/*
сохранит директории/файлы в/var/cache/
, но исключит их содержимое . примерный список*~ *.back /sys /dev /tmp /proc
-
backup.include, у меня пустой, позволяет делать отдельные исключения к exclude, т.е. для примера выше, если вписать
/proc/cpuinfo
, то cpuinfo будет сохраняться. -
backup_cron, правится под ваши нужды, у меня примерно такой:
#!/bin/bash cd /home/backup/backup/ ./backup.sh backup > log/backup-$(date +%H).log 2>&1
Куда его помещать, я уже выше писал, можно и просто crontab -e от root и прописать там в нужно время
Все, осталось под пользователем root создать ssh-ключи и передать их на backup-сервер:
ssh-keygen # (тут главное не ставьте парольную фразу, или заводите ssh-agent, но это другая история)
ssh-copy-id -i ~/.ssh/id_rsa backup@backup.server # спросит пароль пользователя backup, передаст ключ
По сути всё. Что в результате имеем: на сервере в каталоге host1/full хранится полная копия всех файлов на момент последнего запуска скрипта, передаются только измененные файлы, в каталоге host1/incr/YYYY-MM-DD_HH хранится копия перезаписываемого файла (т.е. если файл изменился, перед тем как он запишется в full, он оттуда сохраняется в incr/YYYY-MM-DD_HH, реализуя таким образом схему инкрементного бекапа).
Восстанавливать примерно так:
mkdir restore
./backup.sh restore full/ restore/
./backup.sh restore incr/2010-05-10_14/ restore/
Восстановит в т.ч. и атрибуты и владельца/группу, естественно восстановление нужно делать от пользователя root.
Скрипты я оформил, положил вместе со всеми остальными в git, получить можно:
git clone http://hatred.homelinux.net/git/scripts.git
в каталоге backup, там же посмотрите скрипт hook.d/pacman.sh, сохраняющем список пакетов перед резервированием.
Источники информации в системе
- man rsync
- man rsyncd.conf
- man attr
- man 5 attr
- man mount