Как да архивираме всички бази в MySQL/MariaDB в Ubuntu с bash скрипт

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.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.