Резервное копирование с ротацией бэкапов. Bash скрипт

Со временем у меня возникла потребность сделать более улучшенную версию скрипта для создания бэкапа всего сервера (файлы нескольких сайтов и их БД ), а также загружать на 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/*
На этом все. В примере можете скачать рабочий скрипт, только не забывайте указать свои актуальные доступы и добавить этот скрипт в крон для ежедневного запуска.
Если есть предложения по улучшению или замечания — пишите в комментариях