Часто возникает задача делать backup больших объемов редко изменяющихся файлов. Обычно для этого используют замечательную утилиту rsync
, которая синхронизирует обновленные файлы, чем существенно экономит время бэкапа и сетевой траффик. Количество копий бэкапа, на которые происходит синхронизация, произвольно и чем оно больше — тем лучше. Естественное ограничение — свободное местом носителя. И здесь на помощь приходят две полезные опции рсинка:
--compare-dest=DIR also compare received files relative to DIR --link-dest=DIR hardlink to files in DIR when unchanged
Первая из них создает чисто дифференциальный бэкап сравнением с существующим, то есть помещает в новый бэкап только изменившиеся файлы. Вторая — создает полный бэкап, при этом не изменившиеся файлы с помощью hardlinks ссылаются на забэкапленные. В плане использования свободного места бэкапного сервера различия несущественны, но чисто дифференциальный для использования требует наличия директории сравнения. Основанный на hardlinks — можно сразу использовать «как есть», что намного удобнее. Поэтому, будем рассматривать вариант именно с жесткими ссылками.
Логика бэкапов сделаем наподобие logrotate. Новая директория добавляется с номером 0, при этом существующие сдвигаются на +1 вперед. Количество бэкапов ограничим: последняя директория будет удаляться. Получаем следующий скрипт:
#!/bin/sh servname="mailserv" backup_dir=/backup/$servname/vmail len=60 tmpname=--temp-- curr_dir="$backup_dir/$tmpname" zero_dir="$backup_dir/`printf "%02d" 0`" prev_dir="$backup_dir/`printf "%02d" 1`" last_dir="$backup_dir/`printf "%02d" $len`" date=`date` echo "Starting backup: $date." if [ -d "$zero_dir" ]; then echo "Rotating directories up to $len." # removing last directory if [ -d "$last_dir" ]; then rm -rf "$last_dir" fi # rotating for i in $(seq $len -1 0); do src="$backup_dir/`printf "%02d" $i`" if [ -d "$src" ]; then mv "$src" "$backup_dir/`printf "%02d" $(($i+1))`" fi done fi if [ -d "$curr_dir" ] ; then echo "Warning: \"$curr_dir\" already exists. Probably it was not renamed during last run. Resuming it." fi if [ -d "$prev_dir" ] ; then echo "Making hard-linked incremental backup." rsync -rtzKL --delete --stats --link-dest="$prev_dir" -v $servname:/var/vmail "$curr_dir" # rsync -rtzKL --delete --stats --compare-dest="$prev_dir" $servname:/var/vmail "$curr_dir" else echo "Making init backup." #rsync -rtzKL -e "ssh -i /home/bu/.ssh/id_dsa" --delete --stats $servname:/var/vmail "$curr_dir" rsync -rtzKL --delete --stats $servname:/var/vmail "$curr_dir" fi # moving temporary to latest mv "$curr_dir" "$zero_dir" echo "Backup finished: $date." echo "=================================" echo ""
В результате на файловой системе с поддержкой жестких ссылок можно разместить бэкапов размером на порядки больше, чем размер самого носителя. Например бэкап почтового сервера размером ~870 Gb состоящий из 30 копий занимает всего 970 Gb.
PS: Для систем с разделением прав доступа и разными пользователями такой бэкап желательно делать с опцией --numeric-ids
, которая сохранит (цифровые) owner:group
.
Все бы хорошо, но —numeric-ids требует рутовых прав.