Резервное копирование всей пользовательской информации будем осуществлять в ночное время путём копирования директорий, создания дампа БД с упаковкой сжатием "на лету" всего собранного.
Создаем гнёздышко для резервных копий - в директории, заведомо достаточной по объёму (а объём должен быть не менее половины - учитываем сжатие данных, но не знаем его результативность - оригинального размера исходных файлов сайтов и баз; оценить его можно примерно так: "du -sh /var/lib/mysql/", "du -csh /var/www/*/www/"):
# mkdir -p /var/backups/www
Создаем скрипт еженощного резервирования:
# mkdir -p /usr/local/etc/web
# touch /usr/local/etc/web/backup.nightly.sh
# chmod ug+x /usr/local/etc/web/backup.nightly.sh
# touch /usr/local/etc/web/backup.nightly.sh
# chmod ug+x /usr/local/etc/web/backup.nightly.sh
Строго-настрого закрываем архивы и скрипт от прочтения не уполномоченными:
# chown -R root:root /var/backups/www
# chmod -R g-rwx /var/backups/www
# chown -R root:root /usr/local/etc/web
# chmod -R g-rwx /usr/local/etc/web
# chmod -R g-rwx /var/backups/www
# chown -R root:root /usr/local/etc/web
# chmod -R g-rwx /usr/local/etc/web
Приведем скрипт к следующему виду:
#!/bin/bash
DATE=`date +"%Y%m%d.%H%M%S"`
# Указываем количество файлов резервного копирования которые должны сохранятся на сервере (учитываем, что в результате процедуры резервирования получается два архива: файлов сайтов и их MySQL-баз; например, для трёх сеансов получается шесть файлов)
CPCOUNT=6
# Указываем месторасположение директории хранения архивов резервных копий
BACKDIR="/var/backups/www"
# Указываем пароль суперпользователя (надо бы по другому авторизовать клиента, но об этом не здесь и не сейчас)
MPASWORD="root.password"
# Выясняем количество имеющихся резервных копий и удаляем наиболее старые при превышении заданного лимита, высвобождая пространство для новых копий (делая это до "бэкапа" мы рискуем потерять часть уже имеющихся данных до начала процедуры следующего "бэкапа" - неизвестно ещё насколько удачно тот завершится; но лучше так, чем забить диск до упора, не имея места куда записать новые данные)
if [ "`ls ${BACKDIR} | grep .gz --count`" -gt "${CPCOUNT}" ]; then
# Удаляем два самых старых файла
cd "${BACKDIR}"
ls -t | tail -n 2 | xargs --no-run-if-empty rm --force
fi
# Копируем содержимое web-сайтов как таковых, без служебной и дополнительной пользовательской информации с упаковкой сжатием "на лету" и размещением результата в выделенной для этого директории (здесь утилита tar по мере создания архива в соответствии с опцией "-f -" подаёт его содержимое на "стандартный выход" STDOUT, утилита gzip в соответствии с опцией "-c" получает его через pipe-конвейер со "стандартного входа" STDIN, сжимает, подаёт результат на STDOUT, где поток данных перенаправляется в целевой файл директивой ">")
#
tar -c -f - /var/www/*/www/ | gzip -6 -c > ${BACKDIR}/$DATE.tar.gz
# Создаем "дамп" всех схем MySQL с упаковкой сжатием "на лету"
#
mysqldump --force --quick --complete-insert --all-databases --host=localhost --user=root --password=${MPASWORD} | gzip -6 -c > ${BACKDIR}/$DATE.sql.gz
exit 0
DATE=`date +"%Y%m%d.%H%M%S"`
# Указываем количество файлов резервного копирования которые должны сохранятся на сервере (учитываем, что в результате процедуры резервирования получается два архива: файлов сайтов и их MySQL-баз; например, для трёх сеансов получается шесть файлов)
CPCOUNT=6
# Указываем месторасположение директории хранения архивов резервных копий
BACKDIR="/var/backups/www"
# Указываем пароль суперпользователя (надо бы по другому авторизовать клиента, но об этом не здесь и не сейчас)
MPASWORD="root.password"
# Выясняем количество имеющихся резервных копий и удаляем наиболее старые при превышении заданного лимита, высвобождая пространство для новых копий (делая это до "бэкапа" мы рискуем потерять часть уже имеющихся данных до начала процедуры следующего "бэкапа" - неизвестно ещё насколько удачно тот завершится; но лучше так, чем забить диск до упора, не имея места куда записать новые данные)
if [ "`ls ${BACKDIR} | grep .gz --count`" -gt "${CPCOUNT}" ]; then
# Удаляем два самых старых файла
cd "${BACKDIR}"
ls -t | tail -n 2 | xargs --no-run-if-empty rm --force
fi
# Копируем содержимое web-сайтов как таковых, без служебной и дополнительной пользовательской информации с упаковкой сжатием "на лету" и размещением результата в выделенной для этого директории (здесь утилита tar по мере создания архива в соответствии с опцией "-f -" подаёт его содержимое на "стандартный выход" STDOUT, утилита gzip в соответствии с опцией "-c" получает его через pipe-конвейер со "стандартного входа" STDIN, сжимает, подаёт результат на STDOUT, где поток данных перенаправляется в целевой файл директивой ">")
#
tar -c -f - /var/www/*/www/ | gzip -6 -c > ${BACKDIR}/$DATE.tar.gz
# Создаем "дамп" всех схем MySQL с упаковкой сжатием "на лету"
#
mysqldump --force --quick --complete-insert --all-databases --host=localhost --user=root --password=${MPASWORD} | gzip -6 -c > ${BACKDIR}/$DATE.sql.gz
exit 0
Внесем в таблицу "/etc/crontab" указание на запуск скрипта резервного копирования с определённой периодичностью. Можно и раз в сутки, если не хотим потерять дневную работу клиентов сайта; но я делаю ежедневные инкрементальные бэкапы с помощью централизованной системы резервирования, потому описываемый способ оставляю "на всякий случай", запуская раз в неделю. Выберем субботнее утро, пораньше (в три часа десять минут утра каждой субботы):
# cat /etc/crontab
....
# Nightly backup site objects and database
10 3 * * 6 root /usr/local/etc/web/backup.nightly.sh &
....
# Nightly backup site objects and database
10 3 * * 6 root /usr/local/etc/web/backup.nightly.sh &
....
Самый простой вариант резервирования данных мы настроили. После проведения вышеописанных работ мы будем иметь периодическое копирование всей пользовательской информации, её упаковку и поддержание ротации последних резервных копий.
Нужно понимать, что приведённый вариант настройки подходит только на случай тотальных ошибок самих пользователей, когда требуется восстановления испорченных данных в течении последних десяти суток из имеющегося архива. А вот идея надёжного хранилища резервных копий здесь не реализована, для этого нужно файлы резервных копий выносить на другое оборудование, по возможности максимально удалённое от рабочего.