В прошлой статья было рассмотрено упрощенный вариант бэкапа сайта с возможностью загрузить бэкап на сервер FTP.
Со временем у меня возникла потребность сделать более улучшенную версию скрипта для создания бэкапа всего сервера (файлы нескольких сайтов и их БД ), а также загружать на FTP все это хозяйство c помощью cURL, так как на сервере не было установлен FTP клиент и установить его не было возможности. Также нужно было удалять на FTP сервере старые бэкапы, чтобы не засорялось место на диске.
Бэкап сайтов и Баз Данных
Начнем с настроек. Укажем доступы к БД под которыми будем архивировать Базу Данных:
MUSER="root" MPASS="superpassword" MHOST="localhost"
Зададим путь к каталогу в котором будем архивировать данные с сайтами и куда будем сохранять временные архивы, до выгрузки на FTP:
SITEDIR=/var/www/sites
BACKUP=/var/www/backup
SITEDIR - все директории с сайтами которые лежат внутри этого каталога будут архивироваться в отдельные архивы. Например есть каталоги /var/www/sites/site1.ru и /var/www/sites/site2.ru - соответственно мы получим два архива site1.ru.tar.gz и site2.ru.tar.gz
Далее устанавливаем текущую дату, чтобы помечать бэкапы и было понятно за какой день они сделаны:
NOW=$(date +%Y%m%d)
Указываем путь к бинарникам:
TAR="$(which tar)" GZIP="$(which gzip)" MYSQL="$(which mysql)" MYSQLDUMP="$(which mysqldump)"
Теперь создадим в директории для бэкапов BACKUP временную директорию с текущей датой, туда будем складывать промежуточные архивы с БД и с файлами сайтов, перед тем как загрузим их в общий архив.
mkdir $BACKUP/$NOW
Далее сохраняем в переменную LS список всех сайтов из указанной нами директории SITEDIR, чтобы поочереди их заархивировать.
LS="$(cd $SITEDIR; ls)" for site in $LS do cd $SITEDIR; $TAR -czf $BACKUP/$NOW/$site.tar.gz $site done
Синтаксис "$(...)" указывает что нам нужно выполнить команду внутри скобок и результат выполнения присвоить переменной LS. После этого проходим по директориям циклом в котором сначала переходим в эту директорию, а потом архивируем содержимое. В директорию мы заходили для того чтобы были короткие пути в архивах вида:
site1.ru/index.html
site1.ru/css
site1.ru/css/style.cssа не такого вида:
/var/www/sites/site1.ru/index.html /var/www/sites/site1.ru/css /var/www/sites/site1.ru/css/style.css
После того как мы загнали все сайты в отдельные архивы, нужно теперь их заархивировать в один общий архив для данных сайта.
ARCHIVESITE=$BACKUP/server-$NOW.tar.gz cd $BACKUP/$NOW; $TAR -zcvf $ARCHIVESITE ./
В ARCHIVESITE - указываем что это архив с данными (server) и добавляем дату бэкапа. Потом переходим в директорию NOW и добавляем их в архив.
Теперь можно очистить директорию NOW, для промежуточных бэкапов баз данных.
rm -rf $BACKUP/$NOW/*
В итого у нас получился один архив с данными (файлами) сайтов который покуда лежит в директории ARCHIVESITE. К нему чуть попозже вернемся когда будем загружать бэкапы на FTP.
Переходим дальше к бэкапам Баз Данных.
Изначально подключаемся к MYSQL и просим показать нам список всех БД у данного пользователя. После этого пройдемся циклом по этим базами и заархивируем их и сложим в директорию BACKUP/NOW
DBS="$($MYSQL -u $MUSER -h $MHOST -p$MPASS -Bse 'show databases')" for db in $DBS do if [ $db != 'information_schema' ] then FILE=$BACKUP/$NOW/$db.sql.gz $MYSQLDUMP --add-drop-table --allow-keywords -q -c -u $MUSER -h $MHOST -p$MPASS $db $i | $GZIP -9 > $FILE fi done
Также мы можем отсечь не нужные нам БД, например information_schema которые являются служебными и содержимое их нас не интересует.
Собираем все архивы с БД в один общий и добавляем дату бэкапа
ARCHIVEDB=$BACKUP/mysql-$NOW.tar.gz cd $BACKUP/$NOW; $TAR -zcvf $ARCHIVEDB ./
В ARCHIVEDB - указываем что это архив с Базой Данных (mysql) и добавляем дату бэкапа.
Директорию NOW (и все что в ней есть) можно удалять она нам больше не нужна:
rm -rf $BACKUP/$NOW
После всего этого у нас осталось два архива с файлами и данными:
ARCHIVESITE=$BACKUP/server-$NOW.tar.gz ARCHIVEDB=$BACKUP/mysql-$NOW.tar.gz
Загрузка данных на FTP
Теперь все это дело нужно загрузить как то на FTP, для этих целей мы будем использовать cURL.
Начнем опять же с настроек:
FTPD="dir/to/backup" #директория внутри FTP (вначале и в конце без слеша) FTPU="user" #имя пользователя FTPP="password" #пароль FTPS="site3.ru" #сервер FTP
Задаем количество бэкапов которое нужно сохранять на FTP:
DAYS=5 #дневные бэкапы не считая текущего MONTHS=3 #месячные бэкапы на первое число месяца не считая текущего
Указываем путь к curl:
CURL="$(which curl)"
Дальше переходим в каталог с нашими бэкапами:
cd $BACKUP
И загружаем их на FTP в указанную в настройках директорию:
$CURL -u $FTPU:$FTPP ftp://$FTPS/$FTPD/ -T "{server-$NOW.tar.gz,mysql-$NOW.tar.gz}" -s
Для удаления лишних бэкапов (которым более 5 дней) запрашиваем список всех файлов в директории на FTP:
LIST="$($CURL -u $FTPU:$FTPP ftp://$FTPS/$FTPD/ -s -l)"
Перебираем все файлы в цикле и смотрим чтобы это были файлы типа server-{date}.tar.gz и mysql-{date}.tar.gz. Если дата не совпадает с разрешенной (последние N дней и 1 число последних N месяцев) мы их удаляем:
for li in $LIST do EXIST=0 if [ "$li" = "." ] || [ "$li" = ".." ] then continue fi for day in `seq 0 $DAYS` do d="$(date +%Y%m%d -d "$day days ago")" if [ "server-$d.tar.gz" = "$li" ] || [ "mysql-$d.tar.gz" = "$li" ] then EXIST=1 continue fi done for month in `seq 0 $MONTHS` do d="$(date +%Y%m01 -d "$month month ago")" if [ "server-$d.tar.gz" = $li ] || [ "mysql-$d.tar.gz" = $li ] then EXIST=1 continue fi done if [ $EXIST -eq 0 ] then $CURL -u $FTPU:$FTPP ftp://$FTPS/$FTPD/ -s -X "DELE $li" fi done
И очищаем директорию BACKUP:
rm -rf $BACKUP/*
На этом все. В примере можете скачать рабочий скрипт, только не забывайте указать свои актуальные доступы и добавить этот скрипт в крон для ежедневного запуска.
Если есть предложения по улучшению или замечания - пишите в комментариях
Спасибо большое за скрипт. Очень помог, когда впервые настраивал резервное копирование. Было немного непонятно в статье про параметры DAYS, MONTHS. Также было бы неплохо встроить минимальное логирование на момент настройки скрипта или выложить рядом файл для тестирования крона на случай, правильно ли составлена команда.