Пользователь
0,0
рейтинг
17 сентября 2011 в 12:41

Администрирование → Скрипт резервного копирования через rsync

Возникла необходимость как-то и куда-то бэкапится. Причём чтобы процессоры не грузились и место не занималось, а бэкапы ротэйтились и удобно доставались. Раньше всегда пользовался fsbackup, но захотелось отказаться от архивирования. Для решения задачи была использована rsync и механизм жёстких ссылок (так называемых хардлинков) файловой системы.

Архитектура: есть отдельно стоящий сервер с большим винтом — на нём и работает скрипт. Есть много разных серверов с доступом по ssh, на которых в ~/.ssh/authorized_keys добавлен публичный ключ пользователя, под которым работает скрипт резервного копирования.

Логика работы: в определённое время скрипт по ssh синхронизирует содержимое папки на удалённом сервере с папкой domain.com/latest, а потом копирует её в папку с сегодняшней датой, создавая при этом жёсткие ссылки на файлы, затем удаляет папки, дата создания которых старше 7 дней. Т.к. синхронизируется только содержимое каталога, дампить базу по крону нужно на клиентской машине перед тем, как 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
vovansystems @vovansystems
карма
6,4
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (36)

  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      да, действительно использовать logger правильнее, при возможности разберусь с его документацией

      про ошибку при наличии pid файла — дело в том, что в конце работы скрипта он удаляется безусловно. т.е. если скрипт доработал до конца, его не будет. таким образом наличие этого файла может свидетельстовавать о 1) процесс идёт 2) скрипт убили 3) во время последнего запуска сервера произошла перезагрузка системы. Или как Вы предлагаете?
      • +1
        а использовать конструкцию типа
        if [ -e $PID_FILE ]; than
        if [ -z `ps ax | awk '{ print $1;}' | grep $PID_FILE`]; then
        echo " process $PID_FILE died"
        rm $PID_FILE
        else
        echo " process $PID_FILE still working"
        exit
        fi
        • 0
          действительно! :)
  • +7
    Это неплохо, но не смотрели на rsnapshot? Тот же rsync, + perl.
    • 0
      спасибо — действительно раньше не видел (если бы настроил rsnapshot, отпала бы необходимость писать свой). у него больше возможностей, а принцип работы аналогичен.
  • 0
    А базы mysql можно бекапить rsync-ом?
    • 0
      >дампить базу по крону нужно на клиентской машине перед тем, как rsync заберёт файлы.
    • –2
      вы имеете в виду изпользующиеся в данный момент .MYD .MYI и .frm файлы MySQL?
      • 0
        man mysqldump
        • 0
          как показывает практика дампить базы по 10 гб — немного гиморно. выручает mysqlhotcopy
    • +1
      если вы имеете ввиду сами файлы баз, то можно, но перед «горячим» копированием нужно «заморозить» состояние базы и сбросить кеши. Т.е. в любом случае одним рсинком не обойтись, нужно предварительно совершить некоторые действия с самой базой. Более подробно все расписано в главе 6 официального мануала.
  • +3
    Что только ни придумают, лишь бы не использовать Bacula
    • 0
      Бакула очень тяжело переживает наличие большого количества файлов.
      При бекапе 6 серверов и кол-ве файлов больше миллиона пользоваться бакулой стало просто нереально.
      • 0
        В бакуле есть возможность выполнять скрипты до/после бэкапа. Если места на диске достаточно, то можно все файлы засунуть в архив, скопировать этот архив, затем удалить этот архив. Логичный минус — то что копируется всё скопом, а не выборочно исходя из изменений. Но если места хватает, это даже плюс.
        Проверено, работает.
  • +3
    Уже больше 3х месяцев использую duplicity — масса положительных впечатлений.
    Поддерживает инкрементальные бекапы, указание списка каталогов и исключений (откуда бекапить), шифрацию получившихся файлов (через gnupg), при этом на сервер бекапов отправляет только изменения.

    В итоге работает такая схема:
    1. Выделенный бекап сервер, на него есть доступ с основных серверов
    2. Каждый сервер по крону ежесуточно запускает инкрементальный бекап, еженедельно — полный

    p.s. Получение доступа злоумышленниками к бекап серверу не особо опасно с учётом того, что бекапы зашифрованы.
    • +1
      у duplicity немного другой подход. насколько я знаю, она оперирует только tar файлами, что не всегда удобно (согласен, что с другой стороны не всегда удобно деревья файловой системы в тысячу файлов :) )

      Получение доступа злоумышленниками к бекап серверу не особо опасно с учётом того, что бекапы зашифрованы.
      у них там право только на запись, а не на удаление? я к тому что если сайт дефейснули, не смогут ли злоумышленники просто удалить все бэкапы на удалённом сервере?
      • 0
        Мне намного проще иметь на бекап-сервере десяток больших файлов вместо сотен-тысяч мелких.

        По поводу удаления злоумышленниками — в принципе, могут. Хотя никто не мешает по cron'у на backup сервере файлам менять owner'а (через какое-то время после создания) и оставлять возможность только чтения.
        Конкретно у меня так бекапятся виртуальные сервера, бекапятся из хост-системы, так что риски значительно ниже (linux + openVZ).
        • 0
          в обычных условиях это правильно, а у себя как раз продумываю возможность на несколько часов быстро превратить бэкап-сервер в резервный, на который можно моментально перекинуть днс в случае падения продакшн. хотя это всё на уровне сферического отказоустойчивого сервера в вакууме — игры разума.

          тоже вариант
  • +1
    Эффективнее использовать перенос подняв rsync-демон на бакапном сервере и использовать для авторизации rsync password-file, вместо ssh-ключей. Передача данных в таком случае значительно вырастет, особенно актуально при больших объемах передаваемых данных.
    • 0
      интересно, что там password-file никак не шифруется… а из-за чего рост производительности?
      организовать бы ещё port-knocking...
      • 0
        За счет того, что через протокол rsync'a данные не шифруются ssl
        • +1
          да, но не ssl
          rsa, dsa зависит какой ключ был сгенерирован
  • +1
    duplicity + S3
  • +1
    Пробовали много разных скриптиков бекапа в том числе и fsbackup (больше года на нем сидели), но все это фигня по сравнению с Bacula, попробуйте очень рекомендую
  • +1
    Есть rdiff-backup — делает то же самое, только отлажен и с несколькими плюсами.
  • 0
  • 0
    dirvish.org делает тоже самое, только еще умеет еще удалять старые бэкапы. правда не уверен, что программа все еще поддерживается.
    • 0
      а что значит «удалять старые бэкапы»? тут тоже по истечении срока (7 дней по умолчанию) старые удаляются
      • 0
        агга, сейчас заметил удаление. там настройка более гибкая, типа как в time machine
  • 0
    Прикольно. Пару лет назад я сделал подобное на Perl+rsync. С поддержкой команд на удалённом сервере, чтобы можно было сделать экспорт баз, с параллельным запуском rsync-ов для разных серверов и прочими гибкими настройками. Быкаперы запускаются по крону с разными конфигами, в каждом конфиге описываются сервера, методы доступа к ним, если не дефолтные и количество копий, что надо держать.
  • 0
    Bontmia — работает как часы
  • 0
    Я правильно понимаю, что в случае изменения какого-либо файла в папке latest, он изменится также во всех копиях (в папках названных датами)? То есть папка latest будет отличаться от копий только наличием новых файлов или отсутствием старых?
    • +1
      Вопрос очень хороший, в своё время я сам занимался его изучением. Чтобы на него ответить надо понимать механизм работы rsync по-умолчанию c параметром --delete. man говорит что:

      --delete-before receiver deletes before transfer (default)
      --delete-during receiver deletes during xfer, not before
      --delete-delay find deletions during, delete after
      --delete-after receiver deletes after transfer, not before

      Т.е. при запуске rsync, если параметрами не определено иное, в папке-приёмнике удаляется файл (а так как он существует в папке за предыдущий день — убирается только ссылка на него в папке-приёмнике), а затем под таким же именем создаётся новый файл, в который синхронизируется содержимое из папки-источника.

    • +1
      написал предыдущий коммент и понял что он ничего не объясняет :) вернее всё что там написано относится к файлам, которых больше нет в папке-источнике :)

      а то о чём Вы спрашиваете, происходит из-за механизма работы хардлинков. при модификации одного из файлов, на диске создаётся его модифицированная копия, т.е. происходит так называемый detach хардлинка.

      Допустим есть 2 бэкапа Backup1, Backup 2. Они содержат File1, File2 которые не изменялись и File3, который изменился. Это будет выглядеть так:

      image
  • 0
    Проверил. Всё работает отлично. Гениальное в простоте.
    Было бы еще хорошо если б какой-нть такой же вариант с базами MySql провернуть, а то они получаются архивированными дампами лежат, хотя меняется пара-тройка записей в одной таблице.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.