diff --git a/README.md b/README.md index 175ad8b..7415de6 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,57 @@ # MySQL / MariaDB backup script # -Allows you to create and restore local MySQL / MariaDB backups +Allows you to create and restore local MySQL / MariaDB backups. + +# Requirements # + +Requires a /root/.my.cnf file which contains credentials so the user root can login to the MySQL server with sufficient privileges without entering a password. Example /root/.my.cnf contents: + +``` +[client] +user=root +password=mysecretpassword +``` + +Don't forget to change the permissions: +``` +sudo chmod 600 /root/.my.cnf +``` + +Test if it works with: +``` +PING=$(sudo mysqladmin ping 2>/dev/null) + +if [ "$PING" != "mysqld is alive" ]; then + clear && echo "Error: Unable to connect to MySQL Server!" +else + clear && echo "Successfully connected to the MySQL server!" +fi +``` ## Install script ## ``` -sudo wget -O /usr/local/sbin/backup_mysql.sh +sudo wget -O /usr/local/sbin/backup_mysql.sh https://git.snel.com/snelcom/backup-mysql/raw/branch/master/backup_mysql.sh +sudo chmod 700 /usr/local/sbin/backup_mysql.sh ``` ## Install cronjob ## -TBD +This will add a cronjob to root which will run this script daily at 0:10 am. Adjust as necessary. + +``` +(sudo crontab -l 2>/dev/null; sudo echo '10 0 * * * test -x /usr/local/sbin/backup_mysql.sh && /usr/local/sbin/backup_mysql.sh') | sudo crontab - +``` ## Recover database ## -TBD +Assuming you want to restore mytestdb from your backups made on 20190121-1540: + +``` +DB='mytestdb' +BACKUPDIR='/var/backup/mysql/20190121-1540' +sudo mysql -e "CREATE DATABASE IF NOT EXISTS ${DB}" +sudo -i bash -c 'for table in ${BACKUPDIR}/${DB}/*; do gunzip -c $table | mysql ${DB}; done' +exit +``` diff --git a/backup_mysql.sh b/backup_mysql.sh index 8cee692..5e7627b 100644 --- a/backup_mysql.sh +++ b/backup_mysql.sh @@ -48,9 +48,8 @@ # # # DB='mytestdb' # # BACKUPDIR='/var/backup/mysql/20190121-1540' # -# mysql -e "CREATE DATABASE ${DB}" # -# cd ${BACKUPDIR}/${DB} # -# for table in *; do gunzip -c $table | mysql ${DB}; done # +# mysql -e "CREATE DATABASE IF NOT EXISTS ${DB}" # +# for table in ${BACKUPDIR}/${DB}/*; do gunzip -c $table | mysql ${DB}; done # # # # With myloader (backups should have been created with mydumper): # # # @@ -89,12 +88,12 @@ fi index=0 # Check if we can connect to the mysql server; otherwise die if [ ! "$(id -u -n)" = "root" ]; then - echo -e "Error:: $0 : Only user 'root' can run this script" + echo -e "Error: $0 : Only user 'root' can run this script" exit 100 fi PING=$(mysqladmin ping 2>/dev/null) if [ "$PING" != "mysqld is alive" ]; then - echo "Error:: Unable to connected to MySQL Server, exiting !!" + echo "Error: Unable to connected to MySQL Server, exiting!" exit 101 fi # Backup process starts here. @@ -105,46 +104,46 @@ mysql -e "FLUSH LOGS" if [ $USE_MYDUMPER -eq 1 ]; then # Use mydumper - DB_BKP_FLDR=$BASE_BAK_FLDR/${START_DATETIME} - [ ! -d $DB_BKP_FLDR ] && mkdir -p $DB_BKP_FLDR && chmod 700 $DB_BKP_FLDR - $MYDUMPER -o $DB_BKP_FLDR -G -E -R --less-locking -r 500000 -c -e -L $DB_BKP_FLDR/mydumper.log -v 3 + DB_BKP_FLDR=${BASE_BAK_FLDR}/${START_DATETIME} + [ ! -d ${DB_BKP_FLDR} ] && mkdir -p ${DB_BKP_FLDR} && chmod 700 ${DB_BKP_FLDR} + ${MYDUMPER} -o ${DB_BKP_FLDR} -G -E -R --less-locking -r 500000 -c -e -L ${DB_BKP_FLDR}/mydumper.log -v 3 else # Use traditional mysqldump # Loop through the DB list and create table level backup, # applying appropriate option for MyISAM and InnoDB tables. - for DB in $DBS_LIST; do - DB_BKP_FLDR=$BASE_BAK_FLDR/${START_DATETIME}/$DB - [ ! -d $DB_BKP_FLDR ] && mkdir -p $DB_BKP_FLDR && chmod 700 $DB_BKP_FLDR + for DB in ${DBS_LIST}; do + DB_BKP_FLDR=${BASE_BAK_FLDR}/${START_DATETIME}/${DB} + [ ! -d ${DB_BKP_FLDR} ] && mkdir -p ${DB_BKP_FLDR} && chmod 700 ${DB_BKP_FLDR} # Get the schema of database with the stored procedures. # This will be the first file in the database backup folder - mysqldump -R -d --single-transaction $DB | gzip -c > $DB_BKP_FLDR/000-DB_SCHEMA.sql.gz + mysqldump -R -d --single-transaction ${DB} | gzip -c > ${DB_BKP_FLDR}/000-DB_SCHEMA.sql.gz index=0 #Get the tables and its type. Store it in an array. - table_types=($(mysql -e "show table status from $DB" | awk '{ if ($2 == "MyISAM" || $2 == "InnoDB") print $1,$2}')) + table_types=($(mysql -e "show table status from ${DB}" | awk '{ if ($2 == "MyISAM" || $2 == "InnoDB") print $1,$2}')) table_type_count=${#table_types[@]} # Loop through the tables and apply the mysqldump option according to the table type # The table specific SQL files will not contain any create info for the table schema. # It will be available in SCHEMA file - while [ "$index" -lt "$table_type_count" ]; do + while [ "${index}" -lt "${table_type_count}" ]; do START=$(date +%s) - TYPE=${table_types[$index + 1]} - table=${table_types[$index]} - #echo -en "$(date) : backup $DB : $table : $TYPE " - if [ "$TYPE" = "MyISAM" ]; then - DUMP_OPT="$DB --no-create-info --tables --events --quote-names " + TYPE=${table_types[${index} + 1]} + table=${table_types[${index}]} + #echo -en "$(date) : backup ${DB} : ${table} : ${TYPE} " + if [ "${TYPE}" = "MyISAM" ]; then + DUMP_OPT="${DB} --no-create-info --tables --events --quote-names " else - DUMP_OPT="$DB --no-create-info --single-transaction --tables --events --quote-names " + DUMP_OPT="${DB} --no-create-info --single-transaction --tables --events --quote-names " fi - mysqldump $DUMP_OPT $table |gzip -c > $DB_BKP_FLDR/$table.sql.gz - index=$(($index + 2)) - #echo -e " - Total time : $(($(date +%s) - $START))\n" + mysqldump ${DUMP_OPT} ${table} |gzip -c > ${DB_BKP_FLDR}/${table}.sql.gz + index=$((${index} + 2)) + #echo -e " - Total time : $(($(date +%s) - ${START}))\n" done done fi # Rotating old backup. according to the 'RM_FLDR_DAYS' -if [ ! -z "$RM_FLDR_DAYS" ]; then +if [ ! -z "${RM_FLDR_DAYS}" ]; then #echo -en "$(date) : removing folder : " - find $BASE_BAK_FLDR/ -maxdepth 1 -mtime $RM_FLDR_DAYS -type d -exec rm -rf {} \; + find ${BASE_BAK_FLDR}/ -maxdepth 1 -mtime ${RM_FLDR_DAYS} -type d -exec rm -rf {} \; #echo -fi \ No newline at end of file +fi