Привет.
Тут я расскажу о самом простом способе создания бекапов БД на сервере, о выгрузке их в Яндекс.Диск. Я написал скрипт, который всё это выполняет.
Он приведён поэтапно, можешь скопировать пункты 4.1-4.5, убрав оттуда заголовки, и получишь готовый скрипт. Или можешь скачать, ссылка будет в конце. А лучше прочитать пост и вникнуть в суть происходящего.
ОС на сервере — CentOS 6.7
Версия СУБД — MySQL 5.5 (да, знаю, старая)
Скрипт будет вертеться на сron, конечно же. Это чтобы само всё. Но это в конце.
1. Монтирование Я.Диска в систему.
1.1 Ставим davfs2 систему:
yum install davfs2
1.2 Создаём папку, в которую у нас будет монтироваться удалённое хранилище:
mkdir /mnt/yadisk
1.3 В файл /etc/davfs2/secrets пишем:
/mnt/yadisk полныйадресemail@yandex.ru пароль
1.4 В файле /etc/fstab указываем настройки монтирования хранилища (в одну строку, конечно):
https://webdav.yandex.ru/ /mnt/yadisk davfs user,rw,_netdev,file_mode=600,dir_mode=700 0 1
В конце файла должна быть пустая строка.
Разгадку этого заклинания можно разобрать вот тут: rus-linux.net (отлично всё расписано)
1.5 Тестируем:
mount /mnt/yadisk # монтирование df -h /mnt/yadisk # проверка свободного места
В результате должно отобразиться свободное место на Яндекс.Диске, типа того:
[root@server ~]# mount /mnt/yadisk [root@server ~]# df -h /mnt/yadisk Filesystem Size Used Avail Use% Mounted on https://webdav.yandex.ru/ 10G 1,8G 8,3G 18% /mnt/yadisk
По факту мы имеем обычную с виду директорию, куда можно писать всякое.
umount /mnt/yadisk # Размонтируем диск
Три-четыре. Закончили упражнение.
2. Делаем дампы базы данных
Дамп базы данных создаётся штатной утилитой mysqldump, которая идёт в комплекте с MySQL. Подробнее о ней можно прочесть здесь: MySQL.ru. Я же покажу здесь только необходимое мне самому.
Синтаксис всей команды, например, таков:
mysqldump --host=localhost --user=root --password=1234 -q --default-character-set=utf8 mybigdatabase > /home/mybigdatabase.sql
Разберёмся с этой командой:
—user — Имя пользователя БД
—password — Его пароль
—host — Адрес базы данных (скорее всего это localhost)
—default-character-set — Кодировка текста дампа (скорее всего, это будет utf8)
-q — Вывод текста дампа непосредственно на стандартный вывод stdout без буферизации запроса. Вообще, этот ключик нам необязателен, ибо у нас будет прямая запись вывода в файл. Но без него оно нафиг не надо, а с ним пусть будет.
mybigdatabase — Имя базы данных
> — Перенаправление вывода с перезаписью
/home/mybigdatabase.sql — …например, в этот файл
Можешь поиграться, чего-нибудь подампить, если есть чего.
3. Упаковка дампа
Используем команду gzip таким простым образом:
gzip /home/mybigdatabase.sql
В этой же папке образуется файл mybigdatabase.sql.gz, который меньше исходного на порядки.
Можно использовать tar, но придётся вносить правки в скрипт. Если хочешь заморочиться — пожалуйста, но особой разницы не будет.
tar -czf mybigdatabase.tar.gz /home/mybigdatabase.sql
Всё.
4. Объединение вышеописанного
Теперь определяемся что и зачем будет делать наш скрипт. Всё очень просто:
- Инициализация — готовим переменные, параметры, пути, адреса;
- Создание дампа — собственно, бекапа БД;
- Упаковка дампа — для экономии места;
- Отправка бэкапа в облака — на случай смерти локального файла:
- Монтирование хранилища;
- Копирование файла в хранилище;
- Размонтирование хранилища;
- Завершение — выводим сообщения с результатами и итогами работы скрипта.
Дальше я буду описывать это уже самими командами.
Создаём файл db_backup.sh там, где душе угодно. Мне угодно в домашней папке рута.
Пишем в него нижеследующее.
4.1 Инициализация:
#!/bin/bash # Данные для работы с БД DBHOST=localhost # Адрес БД DBUSER=root # Имя пользователя базы данных DBPASSWD=1234 # Пароль от базы данных DBNAME=mybigdatabase # Имя базы данных для резервного копирования DBCHARSET=utf8 # Кодировка базы данных (utf8) # Даты DATE=`date +%F` # Префикс для структурирования бекапов (формат: 2017-05-22) DATETIME=`date +%F-%H-%M-%S` # Полная текущая дата и время (формат: 2017-05-22-12-23-34) # Локальное хранилище LOCALDIR=/root/db_backup # Полный путь к каталогу, где будут храниться резервные копии LOCALPATH=$LOCALDIR/$DATE # Полный путь к папке за сегодня LOCALFILE=$LOCALPATH/$DBNAME-$DATETIME.sql # Полный путь к файлу дампа LOCALFILEGZ=$LOCALFILE.gz # Полный путь к архиву дампа # Путь к бекапу будет выглядеть так: # /root/db_backup/2017-05-22/mybigdatabase-2017-01-01-12-23-34.sql.gz # Облачное хранилище CLOUDUSE=1 # Копировать ли в облако? Закомментировать строку, если не надо CLOUDMNT=/mnt/yadisk # Точка монтирования облака относительно корня CLOUDDIR=db_backup # Папка в облаке, куда будут лететь файлы (внутри папки CLOUDMNT, т.е. без / в начале) CLOUDPATH=$CLOUDMNT/$CLOUDDIR/$DATE # Полный путь к папке текущей даты в облаке относительно корня CLOUDFILE=$CLOUDPATH/$DBNAME-$DATETIME.sql # Полный путь к файлу дампа в облаке CLOUDFILEGZ=$CLOUDFILE.gz # Полный путь к архиву в облаке # Путь к бекапу на примонтированном хранилище будет выглядеть так: # /mnt/yadisk/db_backup/2017-05-22/mybigdatabase-2017-01-01-12-23-34.sql.gz # Начало процесса echo "[-----------------------------[`date +%F-%H-%M-%S`]-----------------------------]" echo "[`date +%F-%H-%M-%S`] Starting backup"
4.2 Создание дампа:
if ! [[ -d $LOCALPATH ]]; then # Если нет папки за сегодня mkdir $LOCALPATH 2> /dev/null # создаём её, ошибки игнорируем fi echo "[`date +%F-%H-%M-%S`] Generate a database dump: '$DBNAME'..." mysqldump --user=$DBUSER --host=$DBHOST --password=$DBPASSWD -q --default-character-set=$DBCHARSET $DBNAME > $LOCALFILE if [[ $? -gt 0 ]]; then # если дамп сделать не удалось (код завершения предыдущей команды больше нуля) - прерываем весь скрипт echo "[`date +%F-%H-%M-%S`] Dumping failed! Script aborted." exit 1
4.3 Упаковка дампа:
else # иначе - упаковываем его echo "[`date +%F-%H-%M-%S`] Dumping successfull! Packing in GZIP..." gzip $LOCALFILE # Упаковка if [[ $? -ne 0 ]]; then # Если не удалась echo "[`date +%F-%H-%M-%S`] GZipping failed! SQL-file will be uploaded." GZIP_FAILED=1 # Создаём флажок, что упаковка сорвалась else echo "[`date +%F-%H-%M-%S`] Result file: $LOCALFILEGZ" fi
4.4 Отправка в облака:
if [[ $CLOUDUSE -eq 1 ]]; then # Если задано копирование в облако - делаем всякое такое mount | grep "$CLOUDMNT" > /dev/null # Проверяем примонтировано ли уже у нас облако (вывод не важен) if [[ $? -ne 0 ]]; then # Если нет mount $CLOUDMNT # значит монтируем fi if [[ $? -eq 0 ]]; then # если монтирование успешно - копируем туда файл echo "[`date +%F-%H-%M-%S`] Cloud: successfully mounted at $CLOUDMNT" echo "[`date +%F-%H-%M-%S`] Cloud: copying started => $CLOUDFILEGZ" if ! [[ -d $CLOUDPATH ]]; then # Если в облаке нет папки за сегодня mkdir $CLOUDPATH 2> /dev/null # создаём её, ошибки игнорируем fi if [[ -f $LOCALFILEGZ && GZIP_FAILED -ne 1 ]]; then # Если у нас архивирование выше не сорвалось cp -R $LOCALFILEGZ $CLOUDFILEGZ # Копируем архив else cp -R $LOCALFILE $CLOUDFILE # Иначе - копируем большой тяжёлый дамп fi if [[ $? -gt 0 ]]; then # Если не скопировался - просто сообщаем echo "[`date +%F-%H-%M-%S`] Cloud: copy failed." else # Если скопировался - сообщаем и размонтируем echo "[`date +%F-%H-%M-%S`] Cloud: file successfully uploaded!" umount $CLOUDMNT # Размонтирование облака if [[ $? -gt 0 ]]; then # Сообщаем результат размонтирования (если необходимо) echo "[`date +%F-%H-%M-%S`] Cloud: umount - failed!" fi # Конец проверки успешного РАЗмонтирования fi # Конец проверки успешного копирования else # если монтирование НЕуспешно - сообщаем echo "[`date +%F-%H-%M-%S`] Cloud: failed to mount cloud at $CLOUDMNT" fi # Конец проверки успешного монтирования fi # Конец проверки необходимости выгрузки в облако
4.5 Завершение
fi # Конец проверки успешного выполнения mysqldump echo "[`date +%F-%H-%M-%S`] Stat datadir space (USED): `du -h $LOCALPATH | tail -n1`" # вывод размера папки с бэкапами за текущий день echo "[`date +%F-%H-%M-%S`] Free HDD space: `df -h /home|tail -n1|awk '{print $4}'`" # вывод свободного места на локальном диске echo "[`date +%F-%H-%M-%S`] All operations completed!" exit 0 # Успешное завершение скрипта
5. Устанавливаем задачу в cron
Из под root запускаем crontab -e. Подробности по работе с crontab можно найти здесь: Codenet.ru | Ubuntu.ru
В окне запустившегося редактора пишем нижеследующее:
# в качестве командного интерпретатора использовать /bin/sh SHELL=/bin/sh # результаты работы отправлять по этому адресу MAILTO=example@site.com # Запуск скрипта дампа боевой БД и запись в лог 0 8,20 * * * bash ~/db_backup.sh >> ~/db_backup/db_backup.log
Важна последняя команда:
- 0 — в ноль минут
8,20 — в 8 часов утра и 20 часов вечера (без пробела)
* — каждый день
* — каждой недели
* — каждого месяца; - запускается интерпретатор bash;
- который получает путь к скрипту ~/db_backup.sh (а равно /root/db_backup.sh, если всё происходит под рутом);
- выполняет его;
- а вывод дописывается (>>) в файл лога ~/db_backup/db_backup.log
Сразу разъясню простой момент с угловыми скобками:
- > (равносильно 1> ) — перенаправление всего вывода в указанное место с перезаписью. Существующий файл перезаписывается полностью, отсутствующий — создаётся.
- 2> — перенаправление вывода ошибок stderr в указанное место.
Если отправить в /dev/null, то сообщений об ошибках в выводе на экране не окажется. - >> — перенаправление вывода без перезаписи.
Если файла нет — он создаётся, если файл есть — результат дописывается в его конец. Подробнее о перенаправлениях выводов можно прочесть здесь: OpenNET.ru. Там очень богатый функционал и синтаксис.
Пример конечного лога
[-----------------------------[2017-01-01-17-40-50]-----------------------------] [2017-01-01-17-40-50] Run the backup script... [2017-01-01-17-40-50] Generate a database backup: 'mybigdatabase'... [2017-01-01-17-44-17] Dumping successfull! Packing in GZIP... [2017-01-01-17-47-36] Result file: /root/db_backup/2017-01-01/mybigdatabase-2017-01-01-17-40-50.sql.gz [2017-01-01-17-47-38] Cloud: successfully mounted at /mnt/yadisk. [2017-01-01-17-47-38] Cloud: copying started => /mnt/yadisk/db_backup/2017-01-01/mybigdatabase-2017-01-01-17-40-50.sql.gz [2017-01-01-17-48-58] Cloud: file successfully uploaded! [2017-01-01-17-48-58] Stat datadir space (USED): 666M /root/db_backup/2017-01-01 [2017-01-01-17-48-58] Free HDD space: 100500G [2017-01-01-17-48-58] All operations completed!
Заключение
На этом пока всё.
В планах сделать лимиты на объём папок с бекапами. При превышении заданного лимита — удалять старые бекапы.
Это будет во второй версии. Когда-нибудь.
Принимаю инфу об ошибках, критику и предложения.
Скачать готовый скрипт
db_backup.sh (7 kb): Google Drive
Обрати внимание! davfs2 хранит тяжёлый кеш!
День добрый, Скажите может у вас есть решения для меня?
у меня делаются бекапы каждый день по дате
mkdir -p /путь/&data/. туда падают .mp3 файлы с разных магазинов. Так вот как бы мне отслеживать что файлы скопировались из всех магазинов вчерашней датой?
echo `date +%s`|awk ‘{print strftime(«%d.%m.%Y», $1-86400)}’
этим получаем вчерашнею дату.