Инкрементальный backup в дюжину строк
Что самое важное для бекапов? Правильно, воспроизводимость. Поэтому давайте сделаем велосипед на коленке и на опции --link-dest у rsync. У нашего велосипеда не будет сложной структуры данных в стиле git как у restic, ни кучи бекендов как у duplicity. Но мы сможем восстановить его работу по памяти даже под стрессом.
Опция --link-dest позволяет указывать предудущую версию бекапа, на которую rsync будет ставить жёсткие ссылки, если файлы с прошлого раза не поменялись.
То есть, rsync --link-dest=/var/backups/www.1 remote:/var/www /var/backups/www.0 скопирует с удалённого сервера в папку /var/backups/www.0 только те файлы, что поменялись, а на оставшиеся поставит жёсткую ссылку в /var/backups/www.1
Теперь дело за малым: обернуть вызов rsync в код, который сдвигает бекапы на один назад и освобождает место для нового бекапа в /var/backups/www.0, а также удаляет по необходимости последнюю копию /var/backups/www.9.
#отсортировать папочки
Этот код переименует /var/backups/www.1 в /var/backups/www.2 а /var/backups/www.0 переименует в /var/backups/www.1.
Осталось только запустить rsync --link-dest=/var/backups/www.1 remote:/var/www /var/backups/www.0, добавив опции по вкусу. Так опция --delete удаляет файлы в последней копии (rsync этого по умолчанию не делает), опция -C игнорирует папки .svn, .git, артефакты patch и ещё несколько часто встречающихся видов временных файлов.
Всё вместе:
За скобками осталась обработка ошибок (см. set -e) и уведомления, да и количество копий можно сделать настраиваемым.
Опция --link-dest позволяет указывать предудущую версию бекапа, на которую rsync будет ставить жёсткие ссылки, если файлы с прошлого раза не поменялись.
То есть, rsync --link-dest=/var/backups/www.1 remote:/var/www /var/backups/www.0 скопирует с удалённого сервера в папку /var/backups/www.0 только те файлы, что поменялись, а на оставшиеся поставит жёсткую ссылку в /var/backups/www.1
Теперь дело за малым: обернуть вызов rsync в код, который сдвигает бекапы на один назад и освобождает место для нового бекапа в /var/backups/www.0, а также удаляет по необходимости последнюю копию /var/backups/www.9.
find /var/www/backups/ -maxdepth 1 -type d -name '*.[0-9]'| sort -rn| while read dir
do
#выделить циферку из имени папки
this=`expr match "$dir" '.*\([0-9]\)'`;
# увеличить на 1, не забывая, что у нас ограничение на 10 копий
let next=($this+1)%$10;
basedirname=${dir%.[0-9]}
if [ $next -eq 0 ] ; then
rm -rf $dir
else
mv $dir $basedirname.$next
fi
done
Этот код переименует /var/backups/www.1 в /var/backups/www.2 а /var/backups/www.0 переименует в /var/backups/www.1.
Осталось только запустить rsync --link-dest=/var/backups/www.1 remote:/var/www /var/backups/www.0, добавив опции по вкусу. Так опция --delete удаляет файлы в последней копии (rsync этого по умолчанию не делает), опция -C игнорирует папки .svn, .git, артефакты patch и ещё несколько часто встречающихся видов временных файлов.
Всё вместе:
#!/bin/bash
FROM=$1 # откуда
TO=$2 # куда
LINKTO=--link-dest=$TO/`basename $FROM`.1 # предыдущая копия
OPTS="-Ca --delete" # полезные опции для rsync
NUMBER_OF_BACKUPS=10 # столько копий мы храним
# шаманим с переименованием папок, чтобы предыдущие версии сохранялись под именами
# dir.1, dir.2, dir.3 и так далее до dir.9
find $TO -maxdepth 1 -type d -name '*.[0-9]'| sort -rn| while read dir
do
this=`expr match "$dir" '.*\([0-9]\)'`;
let next=($this+1)%$NUMBER_OF_BACKUPS;
basedirname=${dir%.[0-9]}
if [ $next -eq 0 ] ; then
rm -rf $dir
else
mv $dir $basedirname.$next
fi
done
# шаманство закончилось, запускаем rsync
rsync $OPTS $LINKTO $FROM/ $TO/`basename $FROM.0`
За скобками осталась обработка ошибок (см. set -e) и уведомления, да и количество копий можно сделать настраиваемым.
Комментарии
Отправить комментарий