Что самое важное для бекапов? Правильно, воспроизводимость. Поэтому давайте сделаем велосипед на коленке и на опции --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
.
#отсортировать папочки
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
) и уведомления, да и количество копий можно сделать настраиваемым.
Но ведь работает же!
Комментарии (15)
jim945
12.11.2019 23:01Можно же проще.
Пример из скрипта.
snapshotdir="`date +\%Y-\%m-\%d\%R`"
mkdir $backup_dir/$snapshot_dir
rsync -avHXE --delete --delete-excluded --exclude-from=$exclude_file --progress --stats --numeric-ids --link-dest=$backup_dir/last $mnt_dir/ $backup_dir/$snapshot_dir/
rm $backup_dir/last
ln -s $backup_dir/$snapshot_dir $backup_dir/lastmikhailian Автор
12.11.2019 23:15Можно по-всякому. Можно даже без
ln -s
, просто искать в $backup_dir последний по дате снапшот с помощью ну скажемfind $backup_dir -maxdepth 1 -exec stat -c '%n' {} +|tail -n1
и линковать на него.
saboteur_kiev
13.11.2019 02:04А зачем для переименовывания такой большой и ненужный цикл, если можно (echo для наглядности)
for file in {0..9}; do echo mv www.$file www.$(($file+1)); done
mikhailian Автор
13.11.2019 23:19Потому, что бекапов может быть меньше, чем 10.
saboteur_kiev
16.11.2019 01:14Ох, какое непреодолимое препятствие.
for file in {0..9}; do echo if [ -d www.$file ]; then mv www.$file www.$(($file+1)); fi; done
Pinkerton42
13.11.2019 10:34А зачем такой огород, если rsync умеет --backup-dir=$(date +%Y%m%d), который держит актуальную копию данных в отдельном каталоге, а изменившиеся (с момента создания предыдущей копии) файлы складывает в другой с сохранением всей иерархии? Т.е. в результате имеем полную копию всего и рядом историю изменений (между копиями) каждого файла. Без всяких скриптов
Pinkerton42
13.11.2019 11:26поправлюсь… не "… изменившиеся файлы складывает...", а старые версии изменившихся файлов кладет рядом, а в основном снапшоте — всегда актуальные файлы.
mikhailian Автор
13.11.2019 23:23Так ведь хардлинков нет. Они нужны для того, чтобы внутри каждой из папочек www.0, www.1, www.2 содержимое соответствовало копии на момент копирования. Ну и для дедупликации. Вам же не хочется 10 копий одного и того же файла хранить.
Pinkerton42
14.11.2019 04:29Не нужна дедупликация, т.к. ничего "лишнего" не хранится. Рядом по каталогам рассовываются только изменившиеся файлы. В итоге получается, что есть всегда актуальный спапшот каталога-источника и рядом "история" прошлых версий изменившихся файлов:
main folder file1 file2 file3 20191112 file2 20191113 folder file1 file3
Т.е., чтобы получить данные на какую-то конкретную дату, берется каталог "main" и сверху него кладется с заменой каталог с нужной датой.
dphilipo
13.11.2019 10:52вот так я делаю бэкапы.
cp -al делает не копирует файлы, а создает жесткие ссылки на них.
rsync потом копирует и создает только изменившиеся файлы.
В результате получаются директории в которых находятся "снапшоты" копируемой директории.
Если вы копируете какой-нибудь офисный файловый ресурс, то корневую директорию резервных копий можно подключить через плагин теневых копий samba и пользователи будут видеть состояние ресурса на каждый день.
basepath=/path/to/backup today=`date +%Y%m%d` yesterday=`date --date=«yesterday» +%Y%m%d` monthago=`date --date=«30 day ago» +%Y%m%d` todaydir=$basepath/$today yesterdaydir=$basepath/$yesterday monthagodir=$basepath/$monthago mkdir -p $todaydir cp -al $yesterdaydir $todaydir rsync -a --delete /path/to/files/ $todaydir rm -rf $monthagodir
Netbioz
13.11.2019 23:25+1Т.е. получается если похерился или случайно удалил мастер-бекап, все остальные будут нерабочими?
terantul
14.11.2019 06:09скорее частично рабочими.
Теже Бакула\Бареос тоже при потере Фулла, по Инкрементам не всегда смогут восстановить актуальную копию.
ЗЫ. хотя были случаи когда с момента создания Фулла все файлы менялись как минимум один раз. В итоге получилось восстановить актуальную копию только по Инкрементам.
snp
mikhailian Автор
Более половины решений в списке альтернатив restic используют rsync. А вот мы с вами взяли — и использовали его напрямую. We need to go deeper. В следующий раз будем реализовывать rolling hash на голом шелле и netcat.