Появилась задача по резервному копированию сайта на сервере клиента. Необходимо архивировать файлы и базу данных, сжимать с понижением приоритета процесса, и удалять архивы старше 30 дней.

Задача интересна тем, что необходимо производить сжатие архива с понижением приоритета процесса каждый день в 00:00 для того чтобы процесс сжатия минимально конкурировал с основными задачами веб сервера. То есть процесс сжатия должен занимать только свободное время, когда процессор простаивает.

Приоритет процесса

Для реализации этого механизма есть несколько пакетов.

Nice

Команда позволяет вручную установить приоритет.

nice -n 15 tar cvzf files.tar.gz files

Здесь после команды nice в качестве параметра устанавливается значение от -19 до 19, далее пишется команда, на выполнение которой устанавливаем приоритет. Значение -19 наивысший приоритет, 19 - наименьший. Следует учесть, от -1 до -19 может устанавливать только пользователь root, так как эти значение влияют на работу всех процессов и вы должны понимать чем вы занимаетесь. Это следует из того, что по умолчанию системные процессы работают с приоритетом 0, а устанавливая отрицательное значение вы влияете на их работу путем перетягивания процессорного времени на себя. Если параметр -n не задан, то nice устанавливает приоритет 10.

Cpulimit

Эта простая программа позволяет ограничивать процент использования процессорного времени запущенным процессом или группой процессов. Принцип её работы заключается в отслеживании потребляемого процессорного времени указанными процессами путём анализа информации из файловой системы procfs и отправке процессам сигналов SIGSTOP и SIGCONT в определённые моменты времени. Ограничивать можно по идентификатору процесса, по имени процесса или по абсолютному пути до исполняемого файла
по умолчанию программы нет в системе, установка в Debian:

apt-get install cpulimit

Синтаксис

cpulimit --pid=1000 --limit-50

Где --pid = идентификатор процесса, --limit = нагрузка процессора в процентах

cpulimit --exe=tar --limit-50

Где --exe = имя процесса, --limit = нагрузка процессора в процентах

cpulimit --path=/bin/tar --limit-50

Где --path = путь до до программы по абсолютному пути в системе, --limit = нагрузка процессора в процентах

Cgroups

Это механизм в ядре Linux, который даёт возможность изолировать и ограничить ресурсы для групп процессов и их будущих потомков. Это дает возможность при высоких нагрузках распределять ресурсы по заранее заданным правилам между группами процессов. Плюс к этом существует возможность собирать статистику по потребленным ресурсам с помощью специальной подсистемы. Это может применять в любой ситуации, где необходимо распределить ресурсы между конкурирующими процессами и в которой не хватает таких механизмов как nice и т.д. Описание всех возможностей этого механизма требует отдельной статьи, поэтому ограничусь кратким описанием возможностей.
Для работы необходимо установить пакет для пользовательского окружения

apt-get install cgroup-bin

После установки мы вольны выбрать способ управления cgroups:

  • с помощью набора утилит
  • через доступ к виртуальной файловой системе cgroup
  • из собственного программного обеспечения через библиотеку

Самый простой и легко изучаемый способ - использование утилит.

Итак, рассмотрев возможные варианты реализации приоритета процесса, остановился на nice, так как команда уже присутствует в дистрибутиве и использование крайне простое и на мой взгляд идеально подходит именно для нашего случая.

Дамп базы данных и файлов сайта

Для создания резервной копии базы данных напишем исполняемый файл и сделаем его исполнение по крону. Скрипт сделаем универсальным для работы с любыми сайтами.
Параметры как: директория с файлами сайта, директория для хранения резервных копий, имя пользователя базы данных, пароль пользователя базы данных и имя базы данных вынесем из кода и передадим в качестве параметров, тем самым облегчим размер скрипта и повысим удобство чтения.
Параметры к исполняемому файлы передаются через пробел, а в самом файле принимаются в виде $1, $2, $3, что означает порядок следования параметров после имени файла.

Определимся с директорией хранения файлов копий

Первым делом необходимо взглянуть на текущее использование дисков:

df -h
/dev/sda1   455G   31G   402G   7%   /

Места вполне достаточно, значит можем хранить копии в домашней директории пользователя.
Создаем у пользователя директорию bin, в которой разместим файл:

mkdir /home/webmaster/bin

Создаем директорию backups для хранения резервных копий сайта

mkdir /home/webmaster/backups

И файл для хранения логов выполнения резервных копий:

touch /home/webmaster/backups/logs/backup.log

Создаем исполняемый файл

nano /home/webmaster/bin/backup_site.sh

и наполняем его

Код файла для создания резервной копии сайта

#!/bin/bash
#
# $1 - source path
# $2 - destination path
# $3 - user database
# $4 - password for user database
# $5 - name database
#
date=$(date +%Y%m%d)
BACKUP_DIR=$2/${date}
mkdir $BACKUP_DIR
cd $BACKUP_DIR
rsync -av $1/ $BACKUP_DIR/ > /dev/null
nice -n 19 mysqldump -u$3 -p$4 --lock-tables=false --default-character-set=utf8 $5 > $5_${date}.sql
nice -n 19 tar cvzf ../backup_${date}.tar.gz . > /dev/null
chmod -R 777 $BACKUP_DIR
rm -rf $BACKUP_DIR
find $2 -type f -mtime +30 -delete

Пояснения к коду в файле

#!/bin/bash

Указываем желаемый интерпретатор

$1 - путь до директории, где хранятся файлы сайта
$2 - путь до директории, где хранятся резервные копии
$3 - имя пользователя базы данных
$4 - пароль от пользователя базы данных
$5 - имя базы данных

BACKUP_DIR=$2/${date}

Путь директории, в которой хранится копия файлов и дамп БД, создаваемые при выполнении скрипта

date=$(date +%Y%m%d)

Создаем переменную date и устанавливаем в нее текущую дату

mkdir $BACKUP_DIR

Создаем директорию для хранения теущих файлов и дампа БД

cd $BACKUP_DIR

Переходим в нее

rsync -av $1/ $BACKUP_DIR/ > /dev/null

Копируем файлы сайта в директорию созданную выше. Рекомендую использовать rsync так как во время аварийного прекращения выполнения в отличии от cp позволяет при повторном вызове продолижить копирование, а не начинать всё заново.

nice -n 19 mysqldump -u$3 -p$4 --lock-tables=false --default-character-set=utf8 $5 > $5_${date}.sql

Указываем процессу mysqldump приоритет 19 (наименьший), создаем дамп БД с отменой блокировок таблиц и именем файла $5_${date}.sql, где $5 - имя базы данных, ${date} - наша переменная, то есть текущая дата.

nice -n 19 tar cvzf ../backup_${date}.tar.gz . > /dev/null

Указываем процессу tar приоритет 19 (наименьший) и создаем архив с именем backup_${date}.tar.gz, располагающийся на уровень выше и из текущих файлов, где как вы догадались, date - текущая дата

chmod -R 777 $BACKUP_DIR

rm -rf $BACKUP_DIR
Ставим права на все директории и файлы 777 и удаляем

find $2 -type f -mtime +30 -delete

Ищем в директории с резервными копиями файлы старше 30 дней и удаляем их.

Проверка выполнения файла

Прежде чем файл устанавливать в задание для крона, необходимо его проверить. Для этого в консоли выполняем файл с параметрами:

sh ~/bin/backup_site.sh /home/webmaster/example.ru/html /home/webmaster/backups user password database

Параметры:

  • /home/webmaster/example.ru/html - путь до директории с файлами сайта, $1
  • /home/webmaster/backups - путь до директории для хранения резервных копий, $2
  • user - имя пользователя базы данных, $3
  • password - пароль от пользователя базы данных, $4
  • database - имя базы данных, $5

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

Установка задачи резервного копирования по крону

Выполняем команду

crontab -e

Этой командой мы настраиваем задачи крона для текущего пользователя
Устанавливаем задание выполнять резервную копию каждый день в 00:00:

00 00 * * * sh ~/bin/backup_site.sh /home/webmaster/example.ru/html /home/webmaster/backups user password database >> /home/webmaster/backups/logs/backup.log 2>&1

Сохраняем изменения

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

>> /home/webmaster/backups/logs/backup.log 2>&1

>> - двойная стрелка указывает, что записывать лог в конец файла, а одинарная - затирать весь лог файл своими данными
2>&1 - указываем, что надо сохранять все сообщения

Заключение

Скрипт готов, теперь можете архивировать любые сайты.
Кстати, мы предоставляем отличный сервис по резервному копирования сайта в Amazon S3.