Приветствую уважаемое Хабросообщество! Тема бэкапов сайтов на облачное хранилище достаточно широко раскрыта. Но на вопрос: стоит ли изобретать 1001-ый велосипед, я всегда отвечаю — стоит.
Типичная для многих админов ситуация:
- есть виртуальный/невиртуальный сервер;
- есть несколько клиентов, которых вы поддерживаете с момента создания вами сайта;
- есть проблема бэкапов сайтов ваших клиентов.
И почему бы не организовать бэкапы на Я.Диски наших клиентов? Бэкапы не только с файлами, но и с дампами баз данных? И проинструктировать их: не дай бог нам на встречку выедет Камаз, ваши сайты всегда у вас на Я.Диске.
Т.к. мы говорим о Яндексе, мы конечно же делегировали наши домены, на нашем сервере, на Яндекс. Зачем грузить свой сервер? Пусть с почтой, по протоколу smtp, работает Яндекс. А заодно пусть Яндекс и управление NS-ами на себя возьмет. Удобно, на самом деле.
Что нам нужно для организации бэкапов на разные аккаунты Я.Диска:
- установить и настроить ssmtp на ваш сервер;
- установить и настроить нужный клиент Я.Диска;
- создать и настроить bash скрипт для бэкапа;
- прописать задания в cron.
Ну и конечно у нас есть заветная почта вида root@your-site.ru созданная в Яндексе. От имени root@your-site.ru нам будут приходить письма о бэкапах.
Предложенный в статье алгоритм протестирован на сервере с Ubuntu 16.04 на борту.
Устанавливаем, настраиваем, тестируем ssmtp на нашем сервере
Если вы уже отправляете себе письмо с сервера, то пропускаем этот пункт, иначе читаем.
Т.к. пользователей у нас на сервере много, работать придется под суперпользователем root. Тем более, придется прописывать в файл пользователей БД и пароли БД, и пусть все эти данные хранятся в каталоге /root.
Мы же закрыли ssh-коннект для рута? У нас же только один, самый доверенный пользователь может выполнить su?
Выполняем в консоли:
su
cd /root
apt update && apt upgrade
apt install ssmtp
Мы перешли в каталог /root и установили ssmtp. Все дальнейшие команды также будем выполнять в этой директории.
Редактируем конфиг ssmtp:
nano /etc/ssmtp/ssmtp.conf
Приводим его к виду:
root=root@your_site.ru
mailhub=smtp.yandex.ru:465
AuthUser=root@your_site.ru
AuthPass=your_passwd
AuthMethod=LOGIN
FromLineOverride=YES
UseTLS=YES
Hostname=your_site.ru
Конфиг очевиден, комментировать нечего.
Всё! Этого достаточно для решения нашей задачи.
Создадим в /root шаблон письма о наших бэкапах, и проверим работу ssmtp
nano rsync_email_orig
Приведем его к виду:
To: your_email@gmail.com
From: root@your-site
Subject: Backup sites
Info on backup:
Отправляем себе письмо:
cp rsync_email_orig rsync_email_orig_test
echo 'Test msg' >> rsync_email_orig_test
ssmtp your_email@gmail.com < rsync_email_orig_test
rm -f rsync_email_orig_test
Проблем быть не должно, настройка элементарна.
Устанавливаем, настраиваем клиент Я.Диска
Я использую для работы клиент Я.Диска от разработчика Anton Batenev: github.com/abbat/ydcmd
Почему был выбран именно этот клиент:
- можно работать с разными аккаунтами Яндекса;
- можно синхронизировать только то, что нужно.
Для установки ydcmd выполним команды:
sudo add-apt-repository ppa:abbat/ydcmd
sudo apt update
sudo apt install ydcmd
Рассматриваемый нами клиент, есть не что иное как скрипт на python — ydcmd.py, скопированный в /usr/bin. Для работы нам нужно получить токены для Яндекс аккаунтов наших клиентов.
Описывать процесс получения токенов смысла нет. Подробности на Гитхабе: github.com/abbat/ydcmd, или в мануале Яндекса.
После получения токенов создадим разные конфиги для наших клиентов. У меня два разных токена, один общий для всех сайтов, второй для отдельного клиента, с которым заключен договор на обслуживание. Поэтому в статье речь пойдет о двух конфигах: для всех пользователей, и для пользователя vet.
Создаем конфиг по умолчанию, в /root
nano /root/.ydcmd.cfg
Приводим его к виду:
[ydcmd]
token = 1234567890
По аналогии создаём конфиг для пользователя vet, сайты этого пользователя будут бэкапиться на другой Я.Диск.
nano /root/.ydcmd_vet.cfg
Также приведем его к виду:
[ydcmd]
token = any_token
Проверим работу ydcmd для обоих конфигов:
ydcmd stat
ydcmd --config=.ydcmd_vet.cfg stat
В обоих случаях должно быть выведено что-то вроде этого:
name: disk
exif: {}
resource_id: 21239186:e9065863c345ergdfghjfgy51da3c5e06bc12345afeb14158ddcaae
created: 2012-04-04T20:00:00+00:00
modified: 2012-04-04T20:00:00+00:00
path: disk:/
comment_ids: {}
type: dir
revision: 1354646733351472
Как обычно работает:
ydcmd --help
Создадим папки для бэкапов на Я.Дисках:
ydcmd mkdir backup
ydcmd --config=.ydcmd_vet.cfg mkdir backup
На этом с подготовительной частью — всё.
Работает ssmtp, создан шаблон письма о бэкапах, настроен клиент Я.Диска для разных аккаунтов. Напоминаю, что работаем в папке /root.
Готовим bash скрипт для бэкапов
Собственно ничего нового в bash скрипте нет. Компиляция из разных источников, которые я уже не помню. Скрипт работает через день, сохраняются три последние копии. Почему так? Потому что мне так удобнее. Каждый может доработать его под себя.
#!/bin/bash
DATE=`/bin/date '+%d.%m.%Y'`
USER=$1
DIR=/var/www
DIR_SITES=public_html
EMAIL=proctoleha@gmail.com
TEMPLATE_EMAIL=/root/rsync_email
D=`date +%j`
# Четный или нечетный день в году. Остаток от деления на 2 в bash. Можно выставить или == 1, или == 0. Т.е. скрипт будет отрабатывать через день
if [ $((10#$D % 2)) == 1 ];then
case $USER in
vet)
FILE=user_list_vet
cnf=.ydcmd_vet.cfg
DIR_BACKUP=/root/backup_vet
;;
*)
FILE=user_list_all
cnf=.ydcmd.cfg
DIR_BACKUP=/root/backup
;;
esac
else
exit 1
fi
if ! [[ -d $DIR_BACKUP ]]; then
mkdir $DIR_BACKUP
fi
cp rsync_email_orig rsync_email
echo "$DATE" >> $TEMPLATE_EMAIL
echo "==============================================" >> $TEMPLATE_EMAIL
while read line;do
IFS=";"
set -- $line
USER=$1
SITES=$2
DB=$3
DB_USER=$4
DB_PASSWD=$5
FILE_NAME=$DIR_BACKUP/backup_"$SITES"_"$DATE".zip
cd $DIR/$USER/$DIR_SITES
mysqldump -u$DB_USER -p$DB_PASSWD $DB > $DB.sql
zip -r9 $FILE_NAME $SITES $DB.sql > /dev/null
rm ./$DB.sql
zip -T $FILE_NAME >> $TEMPLATE_EMAIL
echo "==============================================" >> $TEMPLATE_EMAIL
chown $USER:$USER $FILE_NAME
done < /root/$FILE
find $DIR_BACKUP/ -mtime +4 -exec rm -f {} ;
/usr/bin/ydcmd --config=/root/$cnf put --rsync $DIR_BACKUP/ disk:/backup >> $TEMPLATE_EMAIL
/usr/sbin/ssmtp $EMAIL < $TEMPLATE_EMAIL
exit 0
Собственно осталось прописать свои переменные здесь:
#home dir
DIR=/var/www
#sites dir
DIR_SITES=public_html
EMAIL=your_email@gmail.com
И здесь, в case:
if [ $((10#$D % 2)) == 1 ];then
case $USER in
vet)
FILE=user_list_vet
cnf=.ydcmd_vet.cfg
DIR_BACKUP=/root/backup_vet
;;
*)
FILE=user_list_all
cnf=.ydcmd.cfg
DIR_BACKUP=/root/backup
;;
esac
else
exit 1
fi
Только непонятно, что такое переменная FILE
FILE=user_list_vet
Переменная FILE не что иное как csv файл, вида:
user1;site1.ru;DB_name1;user_DB_1;passwd_DB_1
user1;site2.ru;DB_name2;user_DB_2;passwd_DB_2
user2;site3.ru;DB_name3;user_DB_3;passwd_DB_3
...
Для каждого бэкапа создаем свой csv файл с своими данными:
имя_системного_пользователя; домен; БД_для_дампа; имя_пользователя_БД; пароль_БД
Естественно имя системного пользователя совпадает с названием домашнего каталога этого пользователя. Пользователь vet — домашний каталог тоже vet.
Создадим нужные csv-файлы для наших бэкапов, отслеживая отсутствие лишних пустых строк в файле! Проверки на пустые строки в скрипте нет!
Т.е. когда создаем csv-файл — курсор, при сохранении, должен находиться в конце последней строки.
Всё готово к пробному запуску.
Еще раз всё проверяем:
- есть шаблон письма rsync_email_orig и работает ssmtp
- настроен клиент Я.Диска ydcmd для разных конфигов
- отредактированы все переменные в rsync.sh
- созданы разные csv файлы для разных бэкапов
Работаем в папке суперпользователя root. Пробуем запустить скрипт для пользователя с небольшим объемом данных, у меня это тестовый пользователь vet, в качестве параметра передаем скрипту имя пользователя:
./rsync.sh vet
Поскольку всё прозрачно и просто, то проблем быть не должно.
На ошибку:
mysqldump: [Warning] Using a password on the command line interface can be insecure.
Внимания не обращаем.
Но может быть и засада: скрипт может просто прекратить работу и ничего не сделать.
Смотрим строки:
# Четный или нечетный день в году. Остаток от деления на 2 в bash. Можно выставить или == 1, или == 0. Т.е. скрипт будет отрабатывать через день
if [ $((10#$D % 2)) == 1 ];then
И меняем 1 на 0, и опять пробуем запустить.
Что должно произойти:
- в указанной в скрипте папке для бэкапов должен быть создана архив с бэкапом вида: backup_your_site.ru_date.zip
- папка для бэкапа будет синхронизирована с Я.Диском для нужного аккаунта
- мы получим письмо вида:
Info on backup: Fri May 12 07:49:15 MSK 2017 ============================================== test of /root/backup_vet/your-site_date.zip OK ==============================================
Собственно всё. Осталось прописать задания в cron.
У меня это выглядит так:
su
crontab -e
00 01 * * * /bin/bash /root/rsync.sh all
00 03 * * * /bin/bash /root/rsynс.sh vet
Как мы видим cron отрабатывает в час ночи и в три часа ночи для разных бэкапов. Сам скрипт будет работать через день.
На этом всё, жду конструктивной критики, замечания и уточнения.
Автор: proctoleha