Написал для себя простенький скрипт (linux bash) для бэкапа всех баз на одном сервере. Его отличительные особенности:
- Наличие списка исключений (т.е. бэкапим все кроме…)
- Получение списка всех БД из MySQL (не надо добавлять вновь созданные базы к бекапу)
- Создание директории под бэкап вида “…/YYYY/mm/dd/HH-MM/”
- Бэкап каждой базы в отдельный файл вида “YYYY-mm-dd.HH-MM.databasename.backup.sql” (mysqldump бэкапит все в один файл)
- Архивирование бэкапа в тарбол
- Зачистка .sql
Собственно к написанию скрипта меня сподвигло именно то что mysqldump бэкапит все что ему сказано в один файл (если требуется восстановить одну базу, то попробуй ее выцарапай из общего дампа…), а создавать отдельную строку для бэкапа всякой новой БД геморно (об этом как минимум надо вспомнить!).
В общем если интересно – прошу под кат:
Собственно сам скрипт
#!/bin/bash ## # MySQL backup utility # @author dmitry.bykadorov@gmail.com ## # current date DATE=`date +%Y-%M-%d` # y/m/d/h/m separately YEAR=`date +%Y` MONTH=`date +%m` DAY=`date +%d` HOURS=`date +%H` MINUTES=`date +%M` # database credentials DBUSER="" DBPASS="" DBHOST="" # create list of databases mysql -h $DBHOST -u $DBUSER -p$DBPASS -e "show databases;" > /tmp/databases.list # create backup dir (e.g. ../2011/01/01/04-00) BACKUP_DIR=/home/backups/mysql/$YEAR/$MONTH/$DAY/$HOURS-$MINUTES mkdir --parents --verbose $BACKUP_DIR # excludes list (Database is a part of SHOW DATABASES output) EXCLUDES=( 'Database' 'information_schema' ) NUM_EXCLUDES=${#EXCLUDES[@]} for database in `cat /tmp/databases.list` do skip=0 let count=0 while [ $count -lt $NUM_EXCLUDES ] ; do # check if this name in excludes list if [ "$database" = ${EXCLUDES[$count]} ] ; then let skip=1 fi let count=$count+1 done if [ $skip -eq 0 ] ; then echo "++ $database" # now we can backup current database cd $BACKUP_DIR backup_name="$YEAR-$MONTH-$DAY.$HOURS-$MINUTES.$database.backup.sql" backup_tarball_name="$backup_name.tar.gz" `/usr/bin/mysqldump -h "$DBHOST" --databases "$database" -u "$DBUSER" --password="$DBPASS" > "$backup_name"` echo " backup $backup_name" `/bin/tar -zcf "$backup_tarball_name" "$backup_name"` echo " compress $backup_tarball_name" `/bin/rm "$backup_name"` echo " cleanup $backup_name" fi done `/bin/rm /tmp/databases.list` echo "done!" |
Можете его свободно:
- использовать (никаких гарантий я вам конечно же не даю – на свой страх и риск )))
- модифицировать (например добавить выгрузку бэкапа на другой сервер или на Amazon S3 )))
- критиковать ))
P.S. Если таки будете использовать – не забудьте подставить ваши mysql credentials ))
Несколько мыслей вслух:
– такой скрипт можно использовать только если к базе не идут интенсивные запросы на изменения (иначе mysqldump не всегда делает консистентный дамп)
– скрипт можно использовать только если реквизиты доступа для всех баз одни
– для реквизитов можно использовать переменные окружения и/или передаваемые параметры
– сжимать можно на лету (это быстрее): | gzip > dump.gz
Привет, Сережа! ) Спасибо что заглянул!
– касательно нагрузки – тут ты безусловно прав. У меня сейчас этот процесс происходит ночью, когда нагрузки практически нет. Но, понятное дело, не всем этот рецепт подойдет. С другой стороны при объемах/нагрузках когда mysqldump может давать неконсистентный дамп, наверное и сам дамп уже настолько объёмен что снимать его невыгодно. Во всяком случае часто и под нагрузкой. Тут уже нужна совсем другая архитектура )
– права доступа на базы, ценное замечание, но я, редиска, пользуюсь суперюзером )
– передача логина/пароля через параметры скрипта мне была не нужна (все-равно пришлось бы в crontab указывать например), а вот переменные окружения стоит попробовать. Хотя чтобы после ребута их не перенабирать – видимо все-равно придется прописать куда-нибудь в init скрипт.
С другой стороны для бекапов можно сделать backup%localhost без пароля с правами на все. Хотя наверное тоже не айс.
А вот насчет “сжимать на лету” – может подскажешь, я как-то все tar да tar, он через перенаправление у меня не фурычит ) Наверное не так готовлю…
А tar в данном случае и не требуется, потому как он архиватор, т. е. собирает кучу файлов один, тут лучше подойдет компрессор, коим gzip и является. А скрипт будет выглядеть примерно так:
В принципе да, можно и на gzip переделать, это реально быстрее, Сережа ‘FatCat’ выше тоже это отметил. Tar я использовал потому как думал что его тоже можно через пайп запустить )
чето не отрабатывает ваш скриптец на дебиане(
root@serever:/home/blind# sh sql.sh
: not found
: not found
: not found
: not found
: not found
‘@’localhost’ (using password: YES)or user ‘root
: not found
mkdir: создан каталог «/home/backups/mysql/2011\r/10\r/30\r/23\r-59\r\r\r»
: not found
sql.sh: 31: Syntax error: “(” unexpected
Ну почему же так категорично ) У меня в bash трудится во всю с момента написания этого поста. @blind: кокой шелл?
Вот тут \r какие-то подозрительные больно. Можешь сам скрипт намылить?
Могу предложить свой вариант.
Основой стал Ваш пример, а я допилил хранение ограниченое кол-во число архивов, и включил в архивацию не олько SQL базы а и каталоги сайтов…
Спасибо за то что поделились опытом )
Спасибо! Очень полезно.
чёт не запускается 🙁
./mysql-backup.sh: 31: Syntax error: word unexpected (expecting “)”)
Вообще скрипт под bash писался, на фряхе сейчас какой шелл по умолчанию? Если доберусь до консоли freebsd на днях, проверю.
freebsd 11