https://www.ubuntu.com/
https://www.mysql.com/
https://mariadb.org/
Този shell скрипт не е нищо особено защото аз не съм bash майстора а и нямам претенции за това но той ми върши една простичка и много важна работа а именно архивира бази дани на сървъри с MySQL и MariaDB. За разлика от файловете базите данни не може просто да се копират и след това да се компресират. Архивирането им се извършва в специален режим за да е сигурно, че по време на операцията не може да се извърши някаква промяна по базата като insert или delete което е неминуем риск за “счупването” на базата. |
В основата си, идеята на скрипта е да архивира всички MySQL/MariaDB бази данни отделно, за да може в по късен етап да се въстанови само една от тях. Разбира се ако изключим функционалноста на скрипта с всичките му подобрения ще получим пет реда код в които той пак ще работи.
#!/bin/bash SH=$(mysql -u root -p<mysqlpass> -Bse 'show databases') for DB in $SH; do FILE="/home/samyil/backup/$DB.sql.gz"; mysqldump --add-drop-database --opt --lock-all-tables -u root -p<mysqlpass> $DB | gzip > $FILE done; |
Но с времето тези пет реда код неусетно станаха над петдесет в стремежа си да го подобря. Основно взимах примери от github, където има всичко, дори за неща които никога няма да се сети човек, но нямаше това което аз точно исках. Така се роди моя малък “Франкенщайн” на bash който присъства на всяко едно “желязо” с MySQL или MariaDB.
Създаване на скрипта
Създаваме файл с текстовия редактор nano mysqlbackup.sh
sudo nano mysqlbackup.sh |
Като в него копираме следното съдържание
#!/bin/bash STORAGEDIR="/mnt/sdb/backup/mysql"; NOW=`date "+%s"`; OLDESTDIR=`ls $STORAGEDIR | head -1`; DATE=`date +%Y-%m-%d` CLOCK=`date +%H:%M:%S` OLDEST=`date -d "$OLDESTDIR" "+%s"`; TODAYDIR="$STORAGEDIR/$DATE"; DIFF=$(($NOW-$OLDEST)); DAYS=$(($DIFF/ (60*60*24))); ROTATION="7" GZIPCHECK=(); MUSER="root"; MPASS="mysqldbpassword"; MHOST="localhost"; MPORT="3306"; IGNOREDB=" information_schema performance_schema mysql test " MYSQL=`which mysql`; MYSQLDUMP=`which mysqldump`; GZIP=`which gzip`; if [ ! -d $TODAYDIR ]; then mkdir -p $TODAYDIR if [ "$?" = "0" ]; then : else echo "Couldn't create folder. Check folder permissions and/or disk quota!" fi else : fi DBS="$(mysql -u $MUSER -p$MPASS -h $MHOST -P $MPORT -Bse 'show databases')" for db in $DBS do DUMP="yes"; if [ "$IGNOREDB" != "" ]; then for i in $IGNOREDB do if [ "$db" == "$i" ]; then DUMP="NO"; fi done fi if [ "$DUMP" == "yes" ]; then FILE="$TODAYDIR/$DATE-$db.sql.gz"; $MYSQLDUMP --add-drop-database --opt --lock-all-tables -u $MUSER -p$MPASS -h $MHOST -P $MPORT $db | gzip > $FILE if [ "$?" = "0" ]; then gunzip -t $FILE; if [ "$?" = "0" ]; then GZIPCHECK+=(1); echo `ls $FILE`; else GZIPCHECK+=(0); echo "Exit, gzip test failed."; fi else echo "Dump of $db failed!" fi fi done; CHECKOUTS=${#GZIPCHECK[@]}; for (( i=0;i<$CHECKOUTS;i++)); do CHECKSUM=$(( $CHECKSUM + ${GZIPCHECK[${i}]} )); done if [ "$CHECKSUM" == "$CHECKOUTS" ]; then echo "" echo "All files checked out ok. Deleting oldest dir."; if [ "$DAYS" -ge $ROTATION ]; then rm -rf $STORAGEDIR/$OLDESTDIR; if [ "$?" = "0" ]; then echo "$OLDESTDIR deleted." else echo "Couldn't delete oldest dir."; echo "Contents of current Backup:"; echo ""; fi else : fi else : fi |
След като копираме скрипта трябва да обърнем специално внимание на променливите като ги редактираме според нашата конфигурация:
STORAGEDIR="/mnt/sdb/backup/mysql";
Това е главната директория в която ще се архивират базите, казвам главната защото ако скрипта се изпълнява всеки ден той ще архивира всички бази за седем дена назад като при всяко негово стартиране ще изтрива осмия ден. Тази седем дневна опция за архивиране доставя спокойствие на администратора от гледна точка на пространство а и никой не иска да търси дадена база в хиляди директории. Тоест в тази директория скрипта ще създаде още седем поддиректории с имена датите на създаването им, и в тях ще съхранява всички бази дани от тези дати. В моя случай съм описал /mnt/sdb/backup/mysql но може да е всяко място което ви хареса, като например например собствената ви директория /home/$user/mysql.
MUSER="root";
MPASS="mysqldbpassword";
MHOST="localhost";
MPORT="3306";
Повече от ясно е предполагам, че трябва да знаете конфигурацията на вашия MySQL или MariaDB сървър и по точно паролата на root. Ако не я знаете значи не сте я създали вие или не са ви я дали което значи, че спирате до тук защото този скрипт е за администратора на машината който иска да архивира всички бази дани със суперпотребителя root а не както често се случва друг потребител без суперправа да си направи архив само на собствените си бази дани.
IGNOREDB="
information_schema
performance_schema
mysql
test
"
Има бази дани който не искаме или няма смисъл да архивираме, тук е мястото да ги опишем:
ROTATION="7"
Седем са дните (директориите) в които се архивират базите. Може да промените числото според вашите нужди, например 10 или 20.
Ако сме готови с конфигурацията трябва да направим нашия скрипт изпълним с командата chmod и е желателно да е със sudo за да може само суперпотребителя (root) да го изпълнява.
sudo chmod 755 mysqlbackup.sh |
Нека изпълним скрипта:
sudo ./mysqlbackup.sh |
Ако всичко е наред скрипта ще покаже в реално време базите които архивира:
Ако скрипта завърши с реда:
All files checked out ok. Deleting oldest dir.
Значи всичко по процедурата с архивирането на базата данни е минала успешно.
За всеки случай можем да хвърлим един бърз поглед на нашите бази с командата ls:
Нека да направим така, че скрипта да се изпълнява всяка сутрин в 5 часа сутринта автоматично без човешка намеса. За целта трябва да редактираме /etc/crontab като добавим следния ред:
0 5 * * * root /home/samyil/mysqlbackup.sh
И рестартираме cron демона за да влязат настройките в сила:
sudo service cron restart |
Въстановяване на MySQL/MariaDB база данни
Накрая някой ще попита:
– А как да въстановя вече архивирана база ?
Разбира се с phpmyadmin, макар,че не винаги се получава по различни причини като най честата е размера на базата.
Спасението разбира се пак е в терминала, нека да дам пример как става това:
Избираме директория с определена дата, например днешна и влизаме в нея:
samyil@host:~$ cd /mnt/sdb/backup/mysql/2016-12-24/ |
Базите са компресирани в gz формат за да се пести място. Базата която искаме да въстановим трябва да я декомпресираме.
sudo gunzip 2016-12-24-igtpleven.sql.gz |
След което файла ще си промени разширението от .sql.gz на .sql и съответно ще стане по голям.
Това е самата команда по въстановяването, в промпта Enter password: трябва да попълним паролата на супепотребителя в mysql root (тоест паролата на mysql която имаме в скрипта)
mysql -u root -p igtpleven < 2016-12-24-igtpleven.sql Enter password:**************** |
Това е всичко, остава да проверим как се държи сайта с въстановената база.
Изпращане на мейл при изпълнение на скрипта
За да запълним и тази дупка в сигурноста един от вариантите за уведомление на събитието е изпращане на мейл. При всяко изпълнение на скрипта аз получавам мейл със списък на всички архивирани бази от току що създадената директория както и също много важно размера им !
Ако вашата машина няма мейл сървър може да използвате relay за такъв или пък само вътрешна поща и да закачите един pop или imap клиент с Thunderbird или Outlook.
Добавете този ред в скрипта най долу като го промените за вашите нужди. mail -s “това в мейла е Относно:” след което следва мейла ви.
echo "$(du -ah $TODAYDIR)" | mail -s "host.itservice-bg.net mysql" robot@telehost.bg |
Това е списъка който получавам всяка сутрин в моя Thunderbird.