Возникла необходимость как-то и куда-то бэкапится. Причём чтобы процессоры не грузились и место не занималось, а бэкапы ротэйтились. Раньше всегда пользовался fsbackup, но захотелось отказаться от архивирования. Для решения задачи была использована rsync и механизм жёстких ссылок (так называемых хардлинков) файловой системы.
Архитектура: есть отдельно стоящий сервер с большим винтом — на нём и работает скрипт. Есть много разных серверов с доступом по ssh, на которых в ~/.ssh/authorized_keys добавлен публичный ключ пользователя, под которым работает скрипт резервного копирования.
Логика работы: в определённое время скрипт по ssh синхронизирует содержимое резервируемой папки с папкой домен/latest, а потом копирует её в папку с сегодняшней датой, создавая при этом жёсткие ссылки на файлы, затем удаляет папки со старыми датами. Т.к. синхронизируется только сожержимое каталога, дампить базу по крону нужно на клиентской машине перед тем, как rsync заберёт файлы.
Плюсы:
– использует меньше места, чем инкрементальные/дифференциальные бэкапы
– меньше грузит процессор, т.к. не использует архиваторы и сжатие данных при передаче по сети
– имеет достаточно подробный формата лога, оповещения по емэйлу об ошибках
– алгоритм устойчив к взлому или полному уничтожению клиентской машины — бэкапы злоумышленник не повредит никак
#!/bin/sh # simple rsync backup script written by farmal.in 2011-01-21 # # latest backup is always in $SDIR/domains/$domain/latest folder # all backups which are older than 7 days would be deleted # backup.ini file can't contain comments, empty lines and spaces in domain names # # example of a GOOD backup.ini: # mydomain.com user@mydomain.com:/path/to/public_html # SDIR="/usr/local/backup" SKEY="$SDIR/.ssh/id_rsa" SLOG="$SDIR/backup.log" PID_FILE="$SDIR/backup.pid" ADMIN_EMAIL="email@domain.com" if [ -e $PID_FILE ]; then echo "this task is already running or previous run was completed with errors on `hostname`" | mail -s "Some mess with backups on `hostname`..." $ADMIN_EMAIL exit fi touch $PID_FILE # redirecting all output to logfile exec >> $SLOG 2>&1 # parsing backup.ini file into $domain and $from variables cat backup.ini | while read domain from ; do destination="$SDIR/domains/$domain" # downloading a fresh copy in 'latest' directory echo -e "`date` *** $domain backup started">>$SLOG # start counting rsync worktime start=$(date +%s) rsync --archive --one-file-system --delete -e "ssh -i $SKEY" "$from" "$destination/latest" || (echo -e "Error when rsyncing $domain. \n\n For more information see $SLOG:\n\n `tail $SLOG`" | mail -s "rsync error" $ADMIN_EMAIL & continue) finish=$(date +%s) echo -e "`date` *** RSYNC worked for $((finish - start)) seconds">>$SLOG # cloning the fresh copy by hardlinking cp --archive --link "$destination/latest" "$destination/`date +%F`" # deleting all previous copies which are older than 7 days by creation date, but not 'latest' find "$destination" -maxdepth 1 -ctime +7 -type d -path "$destination/????-??-??" -exec rm -r -f {} \; echo "`date` *** The size of $domain/latest is now `du -sh $destination/latest | awk '{print $1}'` ">>$SLOG echo -e "`date` *** $domain backup ended">>$SLOG echo -e "`date` *** Total allocated `du -sh $destination | awk '{print $1}'`">>$SLOG echo -e "------------------------------------------------------------------">>$SLOG done rm $PID_FILE |
Прочитал сталью на хабре.
Но аккаунта там не имею, поэтому оставляю комментарий здесь.
Не первый раз вижу подобную реализацию бэкапа и все время думаю: какой смысл в “как бы снэпшетах” реализованных хардлинками? Сама идея таких “снэпшетов” порочна. Они сохраняют состояние поддерева файловой системы на момент резервного копирования только в части касающейся наличия/отсутствия того или иного элемента ФС (файла/каталога), но никак не содержания этих элементов. Это объясняется тем, что при следующей сессии резервного копирования rsync обновит содержание файлов в каталоге latest, а значит обновятся и все файлы в каталогах `date +%F` т.к. и в каталоге latest и в каталогах `date +%F` хардлинки ссылаются на одни и те же inode!
Значит, если бэкапы делаются каждый день, при логическом повреждении какого-либо файла N-ого числа, в N+1 день мы уже не сможем восстановить поврежденный файл на состояние N-1 числа.
Т.о. пользы от псевдоснэпшетов – ноль!
Другое дело, если на сервере резервного копирования использовать честные снэпшеты средствами ФС (например, zfs): будем иметь и статичные во времени копии, и экономию пространства диска (т.к. zfs будет дописывать только изменившиеся/новые блоки файлов).
я тоже через некоторое время после написания скрипта спохватился и про это подумал :) но вскрытие показало что файловая система создаёт новый узел, при попытке изменить тот, на который ссылаются из разных мест (происходит так называемы дитач). подробнее тут
http://habrahabr.ru/blogs/sysadm/128617/#comment_4279281
что касается снэпшотов системы – это оптимальный вариант для бэкапов в пределах одной файловой системы, но скрипт написан для использования на удалённых серверах.
ну как говориться – нет предела совершенству
погоняю недельку другую а там займусь “доведением до совершенства на свой лад ” о результатах отпишусь
буду признателен, если выложите доработанную версию
Pingback: Скрипт резервного копирования через rsync | Unix-системы