Reafactor of xtrabackup scripts
Fix authorized_keys file
Related: PROD-26996(PROD-26996)
(cherry picked from commit 92b8ff4c93103a07d0855820aca03e6d383975e7)
(cherry picked from commit e72102718205baad49fdf569a582fc211fffc071)
Change-Id: I882785b84220cff39667f879ff9ba964dbe47808
diff --git a/xtrabackup/files/innobackupex-client-restore-call.sh b/xtrabackup/files/innobackupex-client-restore-call.sh
index b6798f3..3adafd5 100644
--- a/xtrabackup/files/innobackupex-client-restore-call.sh
+++ b/xtrabackup/files/innobackupex-client-restore-call.sh
@@ -1,52 +1,66 @@
{%- from "xtrabackup/map.jinja" import client with context %}
-#!/bin/sh
-
+#!/bin/bash
+set -eo pipefail
# Purpuse of this script is to locally prepare appropriate backup to restore from local or remote location
-
+# Variables, initiated via salt-formulas/xtrabackup
{%- if client.restore_from == 'remote' %}
-LOGDIR=/var/log/backups
-mkdir -p $LOGDIR
-scpLog=/var/log/backups/innobackupex-restore-scp.log
-echo "Adding ssh-key of remote host to known_hosts"
-ssh-keygen -R {{ client.target.host }} 2>&1 | > $scpLog
-ssh-keyscan {{ client.target.host }} >> ~/.ssh/known_hosts 2>&1 | >> $scpLog
-REMOTEBACKUPPATH=`ssh xtrabackup@{{ client.target.host }} "/usr/local/bin/innobackupex-restore-call.sh {{ client.restore_full_latest }}"`
-echo "Calling /usr/local/bin/innobackupex-restore.sh $REMOTEBACKUPPATH and getting the backup files from remote host"
-/usr/local/bin/innobackupex-restore.sh $REMOTEBACKUPPATH
-
+RESTORE_FROM_MODE="remote"
+CLIENT_TARGET_HOST="{{ client.target.host }}"
+CLIENT_RESTORE_FULL_LATEST="{{ client.restore_full_latest }}"
{%- else %}
+RESTORE_FROM_MODE="local"
+BACKUPDIR="{{ client.backup_dir }}" # Backups base directory
+{%- endif %}
-BACKUPDIR={{ client.backup_dir }} # Backups base directory
-FULL=`find $BACKUPDIR/full -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -{{ client.restore_full_latest }} | tail -1`
-FULL_INCR=`find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -{{ client.restore_full_latest }} | tail -1`
-BEFORE_NEXT_FULL_INCR=`find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$(( {{ client.restore_full_latest }} - 1 )) | tail -1`
+function backup_remote(){
+ local LOGDIR="/var/log/backups"
+ local scpLog="/var/log/backups/innobackupex-restore-scp.log"
+ mkdir -p $LOGDIR
+ echo "Adding ssh-key of remote host to known_hosts"
+ ssh-keyscan ${CLIENT_TARGET_HOST} >> ~/.ssh/known_hosts 2>&1 | >> $scpLog
+ echo "Calling /usr/local/bin/innobackupex-restore.sh $REMOTEBACKUPPATH and getting the backup files from remote host"
+ REMOTEBACKUPPATH="$(ssh xtrabackup@${CLIENT_TARGET_HOST} "/bin/bash /usr/local/bin/innobackupex-restore-call.sh ${CLIENT_RESTORE_FULL_LATEST}")"
+ /usr/local/bin/innobackupex-restore.sh $REMOTEBACKUPPATH
+ ssh-keygen -R ${CLIENT_TARGET_HOST} 2>&1 | > $scpLog
+}
-if [ -z "$FULL" ]; then
+function backup_local(){
+ local FULL="$(find $BACKUPDIR/full -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -${CLIENT_RESTORE_FULL_LATEST}| tail -1)"
+ local FULL_INCR="$(find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -${CLIENT_RESTORE_FULL_LATEST} | tail -1)"
+ local BEFORE_NEXT_FULL_INCR="$(find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$(( ${CLIENT_RESTORE_FULL_LATEST} - 1 )) | tail -1)"
+
+ if [ -z "$FULL" ]; then
echo "Error: No local backup found in $BACKUPDIR/full" >&2
exit 1
-fi
+ fi
-if [ -z "$BEFORE_NEXT_FULL_INCR" ]; then
+ if [ -z "$BEFORE_NEXT_FULL_INCR" ]; then
BEFORE_NEXT_FULL_INCR="Empty"
-fi
+ fi
-if [ "$FULL" = "$FULL_INCR" ]; then
- LATEST_FULL_INCR=`find $BACKUPDIR/incr/$FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1`
- echo "Restoring full backup $FULL starting from its latest incremental $LATEST_FULL_INCR"
- echo "Calling /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
- echo
- /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL_INCR/$LATEST_FULL_INCR
-elif [ "$FULL" = "$BEFORE_NEXT_FULL_INCR" ]; then
- LATEST_FULL_INCR=`find $BACKUPDIR/incr/$BEFORE_NEXT_FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1`
- echo "Restoring full backup $FULL starting from its latest incremental $LATEST_FULL_INCR"
- echo "Calling /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
- echo
- /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR
-else
- echo "Restoring full backup $FULL"
- echo "Calling /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/full/$FULL"
- echo
- /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/full/$FULL
-fi
+ if [ "$FULL" = "$FULL_INCR" ]; then
+ LATEST_FULL_INCR=$(find $BACKUPDIR/incr/$FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1)
+ echo "Restoring full backup $FULL starting from its latest incremental $LATEST_FULL_INCR"
+ echo "Calling /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
+ echo
+ /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL_INCR/$LATEST_FULL_INCR
+ elif [ "$FULL" = "$BEFORE_NEXT_FULL_INCR" ]; then
+ LATEST_FULL_INCR="$(find $BACKUPDIR/incr/$BEFORE_NEXT_FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1)"
+ echo "Restoring full backup $FULL starting from its latest incremental $LATEST_FULL_INCR"
+ echo "Calling /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
+ echo
+ /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR
+ else
+ echo "Restoring full backup $FULL"
+ echo "Calling /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/full/$FULL"
+ echo
+ /usr/local/bin/innobackupex-restore.sh $BACKUPDIR/full/$FULL
+ fi
+}
-{%- endif %}
+# Body ########################################################################
+if [[ ${RESTORE_FROM_MODE} == "remote" ]]; then
+ backup_remote
+ elif [[ ${RESTORE_FROM_MODE} == "local" ]]; then
+ backup_local
+fi
diff --git a/xtrabackup/files/innobackupex-client-restore.sh b/xtrabackup/files/innobackupex-client-restore.sh
index abd08c2..5d8bc4b 100644
--- a/xtrabackup/files/innobackupex-client-restore.sh
+++ b/xtrabackup/files/innobackupex-client-restore.sh
@@ -1,219 +1,220 @@
{%- from "xtrabackup/map.jinja" import client with context %}
{%- from "xtrabackup/map.jinja" import server with context %}
-#!/bin/sh
+#!/bin/bash
#
# Script to prepare and restore full and incremental backups created with innobackupex-runner.
#
# usage example for incr backup restore: ./restore.sh /var/backups/mysql/xtrabackup/incr/2017-05-24_19-48-10/2017-05-24_19-55-35/
-
+set -eo pipefail
#TMPFILE="/var/log/backups/innobackupex-restore.$$.tmp"
+BACKUPDIR="{{ client.backup_dir }}" # Backups base directory
+{%- if client.restore_from == 'remote' %}
+RESTORE_FROM_MODE="remote"
+{%- endif %}
+QPRESS_URL="{{ client.qpress.name }}"
+CLIENT_TARGET_HOST="{{ client.target.host }}"
+SERVERBACKUPDIR="{{ server.backup_dir }}"
TMPFILE="/var/log/backups/innobackupex-restore.log"
-MYCNF=/etc/mysql/my.cnf
-BACKUPDIR={{ client.backup_dir }} # Backups base directory
-FULLBACKUPDIR=$BACKUPDIR/full # Full backups directory
-INCRBACKUPDIR=$BACKUPDIR/incr # Incremental backups directory
-MEMORY=1024M # Amount of memory to use when preparing the backup
-DBALREADYRESTORED=$BACKUPDIR/dbrestored
-scpLog=/var/log/backups/innobackupex-restore-scp.log
-decompressionLog=/var/log/backups/innobackupex-decompression.log
-compression=false
-LOGDIR=/var/log/backups
-
+MYCNF="/etc/mysql/my.cnf"
+FULLBACKUPDIR="$BACKUPDIR/full" # Full backups directory
+INCRBACKUPDIR="$BACKUPDIR/incr" # Incremental backups directory
+MEMORY="1024M" # Amount of memory to use when preparing the backup
+DBALREADYRESTORED="$BACKUPDIR/dbrestored"
+scpLog="/var/log/backups/innobackupex-restore-scp.log"
+decompressionLog="/var/log/backups/innobackupex-decompression.log"
+compression="false"
+LOGDIR="/var/log/backups"
mkdir -p $LOGDIR
+REMOTE_PARENT_DIR="$(dirname $1)"
+BACKUPPATH="$1"
#############################################################################
# Display error message and exit
#############################################################################
-error()
-{
- echo "$1" 1>&2
- exit 1
+error(){
+ echo "$1" 1>&2
+ exit 1
}
#############################################################################
# Check for errors in innobackupex output
#############################################################################
-check_innobackupex_error()
-{
- if [ -z "`tail -1 $TMPFILE | grep 'completed OK!'`" ] ; then
+check_innobackupex_error(){
+ if [ -z "$(tail -1 $TMPFILE | grep 'completed OK!')" ] ; then
echo "$INNOBACKUPEX failed:"; echo
echo "---------- ERROR OUTPUT from $INNOBACKUPEX ----------"
cat $TMPFILE
- #rm -f $TMPFILE
exit 1
fi
}
-# Check options before proceeding
-if [ -e $DBALREADYRESTORED ]; then
- error "Databases already restored. If you want to restore again delete $DBALREADYRESTORED file and run the script again."
-fi
-if [ ! -d $BACKUPDIR ]; then
- error "Backup destination folder: $BACKUPDIR does not exist."
-fi
+function install_qpress(){
+ wget -O qpress.tar ${QPRESS_TAR} > $decompressionLog 2>&1 || true
+ tar -xvf qpress.tar
+ cp qpress /usr/bin/qpress
+ chmod 755 /usr/bin/qpress
+ chown root:root /usr/bin/qpress
+}
-if [ $# != 1 ] ; then
- error "Usage: $0 /absolute/path/to/backup/to/restore"
-fi
-{%- if client.restore_from != 'remote' %}
-
-if [ ! -d $1 ]; then
- error "Backup to restore: $1 does not exist."
-fi
-
-{%- endif %}
-
-# Some info output
-echo "----------------------------"
-echo
-echo "$0: MySQL backup script"
-echo "started: `date`"
-echo
-
-{%- if client.restore_from == 'remote' %}
-#get files from remote and change variables to local restore dir
-
-LOCALRESTOREDIR=/var/backups/restoreMysql
-REMOTE_PARENT_DIR=`dirname $1`
-BACKUPPATH=$1
-FULLBACKUPDIR=$LOCALRESTOREDIR/full
-INCRBACKUPDIR=$LOCALRESTOREDIR/incr
-
-mkdir -p $LOCALRESTOREDIR
-rm -rf $LOCALRESTOREDIR/*
-
-echo "Getting files from remote host"
-
-case "$BACKUPPATH" in
- *incr*) echo "SCP getting full and incr backup files";
- FULL=`basename $REMOTE_PARENT_DIR`;
- mkdir -p $FULLBACKUPDIR;
- mkdir -p $INCRBACKUPDIR;
- PARENT_DIR=$INCRBACKUPDIR/$FULL;
- `scp -rp xtrabackup@{{ client.target.host }}:$REMOTE_PARENT_DIR/ $INCRBACKUPDIR/ >> $scpLog 2>&1`;
- `scp -rp xtrabackup@{{ client.target.host }}:{{ server.backup_dir }}/full/$FULL/ $FULLBACKUPDIR/$FULL/ >> $scpLog 2>&1`;;
- *full*) echo "SCP getting full backup files";
- FULL=`basename $1`;
- mkdir -p $FULLBACKUPDIR;
- PARENT_DIR=$FULLBACKUPDIR;
- `scp -rp xtrabackup@{{ client.target.host }}:{{ server.backup_dir }}/full/$FULL/ $FULLBACKUPDIR/$FULL/ >> $scpLog 2>&1`;;
- *) echo "Unable to scp backup files from remote host"; exit 1 ;;
-esac
-
-# Check if the scp succeeded or failed
-if ! grep -q "No such file or directory" $scpLog; then
- echo "SCP from remote host completed OK"
-else
- echo "SCP from remote host FAILED"
- exit 1
-fi
-
-{%- else %}
-
-PARENT_DIR=`dirname $1`
-
-{%- endif %}
-
-if [ $PARENT_DIR = $FULLBACKUPDIR ]; then
-{%- if client.restore_from == 'remote' %}
- FULLBACKUP=$FULLBACKUPDIR/$FULL
-{%- else %}
- FULLBACKUP=$1
-{%- endif %}
-
- for bf in `find . $FULLBACKUP -iname "*\.qp"`; do compression=True; break; done
-
- if [ "$compression" = True ]; then
- if hash qpress 2>>$TMPFILE; then
- echo "qpress already installed" >> $TMPFILE
- else
-{%- if client.qpress.source == 'tar' %}
- wget {{ client.qpress.name }} > $decompressionLog 2>&1
- tar -xvf qpress-11-linux-x64.tar
- cp qpress /usr/bin/qpress
- chmod 755 /usr/bin/qpress
- chown root:root /usr/bin/qpress
-{%- endif %}
- fi
- echo "Uncompressing $FULLBACKUP"
- for bf in `find . $FULLBACKUP -iname "*\.qp"`; do qpress -d $bf $(dirname $bf) && rm $bf; done > $decompressionLog 2>&1
+function prerequisites(){
+ # Check options before proceeding
+ if [ -e $DBALREADYRESTORED ]; then
+ error "Databases already restored. If you want to restore again delete $DBALREADYRESTORED file and run the script again."
fi
- echo "Restore `basename $FULLBACKUP`"
+ if [ ! -d $BACKUPDIR ]; then
+ error "Backup destination folder: $BACKUPDIR does not exist."
+ fi
+
+ if [ $1 != 1 ] ; then
+ error "Usage: $2 /absolute/path/to/backup/to/restore"
+ fi
+
+ if [[ ${RESTORE_FROM_MODE} != "remote" ]]; then
+ if [ ! -d $BACKUPPATH ]; then
+ error "Backup to restore: $BACKUPPATH does not exist."
+ fi
+ fi
+}
+
+function scp_data(){
+ # Some info output
+ echo "----------------------------"
echo
-else
- if [ `dirname $PARENT_DIR` = $INCRBACKUPDIR ]; then
- INCR=`basename $1`
- FULL=`basename $PARENT_DIR`
- FULLBACKUP=$FULLBACKUPDIR/$FULL
+ echo "$0: MySQL backup script"
+ echo "started: $(date)"
+ echo
+ if [[ ${RESTORE_FROM_MODE} == "remote" ]]; then
+ #get files from remote and change variables to local restore dir
+ LOCALRESTOREDIR="/var/backups/restoreMysql"
+ FULLBACKUPDIR="$LOCALRESTOREDIR/full"
+ INCRBACKUPDIR="$LOCALRESTOREDIR/incr"
- if [ ! -d $FULLBACKUP ]; then
- error "Full backup: $FULLBACKUP does not exist."
+ mkdir -p $LOCALRESTOREDIR
+ rm -rf $LOCALRESTOREDIR/*
+
+ echo "Getting files from remote host"
+
+ case "$BACKUPPATH" in
+ *incr*) echo "SCP getting full and incr backup files";
+ FULL=$(basename $REMOTE_PARENT_DIR);
+ mkdir -p $FULLBACKUPDIR;
+ mkdir -p $INCRBACKUPDIR;
+ PARENT_DIR="$INCRBACKUPDIR/$FULL";
+ $(scp -rp xtrabackup@$CLIENT_TARGET_HOST:$REMOTE_PARENT_DIR/ $INCRBACKUPDIR/ >> $scpLog 2>&1);
+ $(scp -rp xtrabackup@$CLIENT_TARGET_HOST:$SERVERBACKUPDIR/full/$FULL/ $FULLBACKUPDIR/$FULL/ >> $scpLog 2>&1);;
+ *full*) echo "SCP getting full backup files";
+ FULL=$(basename $BACKUPPATH);
+ mkdir -p $FULLBACKUPDIR;
+ PARENT_DIR=$FULLBACKUPDIR;
+ $(scp -rp xtrabackup@$CLIENT_TARGET_HOST:$SERVERBACKUPDIR/full/$FULL/ $FULLBACKUPDIR/$FULL/ >> $scpLog 2>&1);;
+ *) echo "Unable to scp backup files from remote host"; exit 1 ;;
+ esac
+
+ # Check if the scp succeeded or failed
+ if ! grep -q "No such file or directory" $scpLog; then
+ echo "SCP from remote host completed OK"
+ else
+ echo "SCP from remote host FAILED"
+ exit 1
fi
- for bf in `find . $FULLBACKUP -iname "*\.qp"`; do compression=True; break; done
+ else
+ PARENT_DIR="$(dirname $BACKUPPATH)"
+ fi
+
+}
+
+function restore_preperation(){
+ if [ $PARENT_DIR = $FULLBACKUPDIR ]; then
+ if [[ ${RESTORE_FROM_MODE} == "remote" ]]; then
+ FULLBACKUP=$FULLBACKUPDIR/$FULL
+ else
+ FULLBACKUP=$BACKUPPATH
+ fi
+ for bf in $(find . $FULLBACKUP -iname "*\.qp"); do compression=True; break; done
if [ "$compression" = True ]; then
- if hash qpress 2>>$decompressionLog; then
- echo "qpress already installed" >> $decompressionLog
+ if hash qpress 2>>$TMPFILE; then
+ echo "qpress already installed" >> $TMPFILE
else
-{%- if client.qpress.source == 'tar' %}
- wget {{ client.qpress.name }} > $decompressionLog 2>&1
- tar -xvf qpress-11-linux-x64.tar
- cp qpress /usr/bin/qpress
- chmod 755 /usr/bin/qpress
- chown root:root /usr/bin/qpress
-{%- endif %}
+ install_qpress
fi
echo "Uncompressing $FULLBACKUP"
- for bf in `find . $FULLBACKUP -iname "*\.qp"`; do qpress -d $bf $(dirname $bf) && rm $bf; done > $decompressionLog 2>&1
- echo "Uncompressing $PARENT_DIR"
- for bf in `find . $PARENT_DIR -iname "*\.qp"`; do qpress -d $bf $(dirname $bf) && rm $bf; done >> $decompressionLog 2>&1
+ for bf in $(find . $FULLBACKUP -iname "*\.qp"); do qpress -d $bf $(dirname $bf) && rm $bf; done > $decompressionLog 2>&1
fi
+ echo "Restore $(basename $FULLBACKUP)"
echo
- echo "Restore $FULL up to incremental $INCR"
- echo
+ else
+ if [ $(dirname $PARENT_DIR) = $INCRBACKUPDIR ]; then
+ INCR="$(basename $BACKUPPATH)"
+ FULL="$(basename $PARENT_DIR)"
+ FULLBACKUP="$FULLBACKUPDIR/$FULL"
- echo "Replay committed transactions on full backup"
- innobackupex --defaults-file=$MYCNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP > $TMPFILE 2>&1
- check_innobackupex_error
- # Apply incrementals to base backup
- for i in `find $PARENT_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n`; do
- echo "Applying $i to full ..."
- innobackupex --defaults-file=$MYCNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP --incremental-dir=$PARENT_DIR/$i > $TMPFILE 2>&1
+ if [ ! -d $FULLBACKUP ]; then
+ error "Full backup: $FULLBACKUP does not exist."
+ fi
+
+ for bf in $(find . $FULLBACKUP -iname "*\.qp"); do compression=True; break; done
+
+ if [ "$compression" = True ]; then
+ if hash qpress 2>>$decompressionLog; then
+ echo "qpress already installed" >> $decompressionLog
+ else
+ install_qpress
+ fi
+ echo "Uncompressing $FULLBACKUP"
+ for bf in $(find . $FULLBACKUP -iname "*\.qp"); do qpress -d $bf $(dirname $bf) && rm $bf; done > $decompressionLog 2>&1
+ echo "Uncompressing $PARENT_DIR"
+ for bf in $(find . $PARENT_DIR -iname "*\.qp"); do qpress -d $bf $(dirname $bf) && rm $bf; done >> $decompressionLog 2>&1
+ fi
+
+ echo
+ echo "Restore $FULL up to incremental $INCR"
+
+ echo "Replay committed transactions on full backup"
+ innobackupex --defaults-file="$MYCNF" --apply-log --redo-only --use-memory="$MEMORY" $FULLBACKUP > $TMPFILE 2>&1 || true
check_innobackupex_error
- if [ $INCR = $i ]; then
- break # break. we are restoring up to this incremental.
- fi
- done
- else
- error "unknown backup type"
+ # Apply incrementals to base backup
+ for i in $(find $PARENT_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n); do
+ echo "Applying $i to full ..."
+ innobackupex --defaults-file=$MYCNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP --incremental-dir=$PARENT_DIR/$i > $TMPFILE 2>&1 || true
+ check_innobackupex_error
+
+ if [ $INCR = $i ]; then
+ break # break. we are restoring up to this incremental.
+ fi
+ done
+ else
+ error "unknown backup type"
+ fi
fi
-fi
+}
+function restore(){
+ echo "Preparing ..."
+ innobackupex --defaults-file=$MYCNF --apply-log --use-memory=$MEMORY $FULLBACKUP > $TMPFILE 2>&1 || true
+ check_innobackupex_error
-echo "Preparing ..."
-innobackupex --defaults-file=$MYCNF --apply-log --use-memory=$MEMORY $FULLBACKUP > $TMPFILE 2>&1
-check_innobackupex_error
+ echo "Restoring ..."
+ innobackupex --defaults-file=$MYCNF --copy-back $FULLBACKUP > $TMPFILE 2>&1 || true
+ check_innobackupex_error
+ chown -R mysql:mysql /var/lib/mysql
+ #rm -f $TMPFILE
+ touch $DBALREADYRESTORED
+ echo "Backup restored successfully. You are able to start mysql now."
+ echo "Verify files ownership in mysql data dir."
+ #echo "Run 'chown -R mysql:mysql /path/to/data/dir' if necessary."
+ echo "completed: $(date)"
+ exit 0
+}
-echo
-echo "Restoring ..."
-innobackupex --defaults-file=$MYCNF --copy-back $FULLBACKUP > $TMPFILE 2>&1
-check_innobackupex_error
-chown -R mysql:mysql /var/lib/mysql
-#rm -f $TMPFILE
-touch $DBALREADYRESTORED
-echo "Backup restored successfully. You are able to start mysql now."
-echo "Verify files ownership in mysql data dir."
-#echo "Run 'chown -R mysql:mysql /path/to/data/dir' if necessary."
-echo
-echo "completed: `date`"
-exit 0
-{#
-# vim: ft=jinja
-#}
+prerequisites "$#" "$0"
+scp_data
+restore_preperation
+restore
diff --git a/xtrabackup/files/innobackupex-client-runner.sh b/xtrabackup/files/innobackupex-client-runner.sh
index fb20ac4..a0ae1ac 100644
--- a/xtrabackup/files/innobackupex-client-runner.sh
+++ b/xtrabackup/files/innobackupex-client-runner.sh
@@ -1,15 +1,14 @@
-{%- from "xtrabackup/map.jinja" import client with context %}
{%- from "xtrabackup/map.jinja" import server with context %}
-#!/bin/sh -eo pipefile
+{%- from "xtrabackup/map.jinja" import client with context %}
+
+#!/bin/bash
#
# Script to create full and incremental backups (for all databases on server) using innobackupex from Percona.
# http://www.percona.com/doc/percona-xtrabackup/innobackupex/innobackupex_script.html
#
# Every time it runs will generate an incremental backup except for the first time (full backup).
# FULLBACKUPLIFE variable will define your full backups schedule.
-
-SKIPCLEANUP=false
-FORCEFULL=false
+set -eo pipefail
usage () {
echo ""
@@ -20,238 +19,256 @@
echo " -h shows this help"
}
+SKIPCLEANUP="false"
+FORCEFULL="false"
while getopts ":sfh" opt; do
- case $opt in
- s)
- echo "Cleanup will be skipped" >&2
- SKIPCLEANUP=true
- ;;
- f)
- echo "Full backup will be force triggered"
- FORCEFULL=true
- ;;
- h)
- usage
- exit 0
- ;;
- \?)
- echo "Invalid option: -$OPTARG" >&2
- usage
- exit 1
- ;;
- esac
+ case $opt in
+ s)
+ echo "Cleanup will be skipped" >&2
+ SKIPCLEANUP="true"
+ ;;
+ f)
+ echo "Full backup will be force triggered"
+ FORCEFULL="true"
+ ;;
+ h)
+ usage
+ exit 0
+ ;;
+ \?)
+ echo "Invalid option: -$OPTARG" >&2
+ usage
+ exit 1
+ ;;
+ esac
done
USEROPTIONS="--user={{ client.database.user }} --password={{ client.database.password }}{%- if client.database.host is defined %} --host {{ client.database.host }} --port {{ client.database.get('port', '3306') }}{%- else %} --socket=/var/run/mysqld/mysqld.sock{%- endif %}"
#TMPFILE="/var/log/backups/innobackupex-runner.$$.tmp"
-LOGDIR=/var/log/backups
+LOGDIR="/var/log/backups"
TMPFILE="/var/log/backups/innobackupex-runner.log"
-MYCNF=/etc/mysql/my.cnf
-MYSQL=/usr/bin/mysql
-MYSQLADMIN=/usr/bin/mysqladmin
-BACKUPDIR={{ client.backup_dir }} # Client side backups base directory
-SERVERBACKUPDIR={{ server.backup_dir }} # Server side backups base directory
-FULLBACKUPDIR=$BACKUPDIR/full # Full backups directory
-INCRBACKUPDIR=$BACKUPDIR/incr # Incremental backups directory
-KEEP={{ client.full_backups_to_keep }} # Number of full backups (and its incrementals) to keep
+MYCNF="/etc/mysql/my.cnf"
+MYSQL="/usr/bin/mysql"
+MYSQLADMIN="/usr/bin/mysqladmin"
+BACKUPDIR="{{ client.backup_dir }}" # Client side backups base directory
+SERVERBACKUPDIR="{{ server.backup_dir }}" # Server side backups base directory
+SERVERBACKUPHOST="{{ client.target.host }}"
+FULLBACKUPDIR="$BACKUPDIR/full" # Full backups directory
+INCRBACKUPDIR="$BACKUPDIR/incr" # Incremental backups directory
+KEEP="{{ client.full_backups_to_keep }}" # Number of full backups (and its incrementals) to keep
{%- if client.backup_times is defined %}
-INCRBEFOREFULL={{ client.incr_before_full }}
+INCRBEFOREFULL="{{ client.incr_before_full }}"
{%- else %}
-HOURSFULLBACKUPLIFE={{ client.hours_before_full }} # Lifetime of the latest full backup in hours
-FULLBACKUPLIFE=$(( $HOURSFULLBACKUPLIFE * 60 * 60 ))
+HOURSFULLBACKUPLIFE="{{ client.hours_before_full }}" # Lifetime of the latest full backup in hours
+FULLBACKUPLIFE="$(( $HOURSFULLBACKUPLIFE * 60 * 60 ))"
{%- endif %}
-
-rsyncLog=/var/log/backups/innobackupex-rsync.log
-
+rsyncLog="/var/log/backups/innobackupex-rsync.log"
{%- if client.compression is defined %}
-compression={{ client.compression }}
+compression="{{ client.compression }}"
{%- else %}
-compression=false
+compression="false"
{%- endif %}
-
{%- if client.compression_threads is defined %}
-compression_threads={{ client.compression_threads }}
+compression_threads="{{ client.compression_threads }}"
{%- else %}
-compression_threads=1
+compression_threads="1"
{%- endif %}
-
-mkdir -p $LOGDIR
+{%- if client.throttle is defined %}
+throttle="--throttle {{ client.get('throttle', 20) }}"
+{%- else %}
+throttle=""
+{%- endif %}
+{%- if client.backup_times is defined %}
+BACKUPTIME="true"
+{%- endif %}
# Grab start time
-STARTED_AT=`date +%s`
+STARTED_AT="$(date +%s)"
#############################################################################
# Display error message and exit
#############################################################################
error()
{
- echo "$1" 1>&2
- exit 1
+ echo "$1" 1>&2
+ exit 1
}
-# Check prerequisites before proceeding
-if [ ! -d $BACKUPDIR ]; then
- error "Backup destination folder: $BACKUPDIR does not exist."
-fi
+function prerequisites()
+{
+ # Check prerequisites before proceeding
+ if [ ! -d $BACKUPDIR ]; then
+ error "Backup destination directory: $BACKUPDIR does not exist."
+ fi
-if [ -z "`$MYSQLADMIN $USEROPTIONS status | grep 'Uptime'`" ] ; then
- error "HALTED: MySQL does not appear to be running."
-fi
+ if [ -z "$($MYSQLADMIN $USEROPTIONS status | grep 'Uptime')" ] ; then
+ error "HALTED: MySQL does not appear to be running."
+ fi
-if ! `echo 'exit' | $MYSQL -s $USEROPTIONS` ; then
- error "HALTED: Supplied mysql username or password appears to be incorrect (not copied here for security, see script)."
-fi
+ if ! $(echo 'exit' | $MYSQL -s $USEROPTIONS) ; then
+ error "HALTED: Supplied mysql username or password appears to be incorrect (not copied here for security, see script)."
+ fi
-# Some info output
-echo "----------------------------"
-echo
-echo "$0: MySQL backup script"
-echo "started: `date`"
-echo
-
-# Create full and incr backup directories if they not exist.
-mkdir -p $FULLBACKUPDIR
-mkdir -p $INCRBACKUPDIR
-
-# Find latest full backup
-LATEST_FULL=`find $FULLBACKUPDIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1`
-
-# Get latest backup last modification time
-LATEST_FULL_CREATED_AT=`stat -c %Y $FULLBACKUPDIR/$LATEST_FULL`
-
-# If compression is enabled, pass it on to the backup command
-if [ "$compression" = True ]; then
- compress="--compress"
- compression_threads="--compress-threads=$compression_threads"
- echo "Setting compression to True"
+ # Some info output
+ echo "----------------------------"
+ echo "$0: MySQL backup script"
+ echo "started: $(date)"
echo
-else
- compress=
- compression_threads=
-fi
-# If throttling is enabled, pass it on to the backup command
-{%- if client.throttle is defined %}
-echo "Setting throttling to True, IO limit is {{ client.get('throttle', '20') }}MB"
-throttle="--throttle {{ client.get('throttle', 20) }}"
-{%- else %}
-throttle=""
-{%- endif %}
-
-{%- if client.backup_times is not defined %}
-# Run an incremental backup if latest full is still valid. Otherwise, run a new full one.
-if [ "$LATEST_FULL" -a `expr $LATEST_FULL_CREATED_AT + $FULLBACKUPLIFE + 5` -ge $STARTED_AT ] ; then
- # Create incremental backups dir if not exists.
- TMPINCRDIR=$INCRBACKUPDIR/$LATEST_FULL
- mkdir -p $TMPINCRDIR
-
- # Find latest incremental backup.
- LATEST_INCR=`find $TMPINCRDIR -mindepth 1 -maxdepth 1 -type d | sort -nr | head -1`
-
- # If this is the first incremental, use the full as base. Otherwise, use the latest incremental as base.
- if [ ! $LATEST_INCR ] ; then
- INCRBASEDIR=$FULLBACKUPDIR/$LATEST_FULL
- else
- INCRBASEDIR=$LATEST_INCR
+ if [ ! -d $LOGDIR ]; then
+ echo "Creating destination directory $LOGDIR."
+ mkdir -p $LOGDIR
+ fi
+ if [ ! -d $FULLBACKUPDIR ]; then
+ echo "Creating destination directory $FULLBACKUPDIR".
+ mkdir -p $FULLBACKUPDIR
+ fi
+ if [ ! -d $INCRBACKUPDIR ]; then
+ echo "Creating destination directory $INCRBACKUPDIR".
+ mkdir -p $INCRBACKUPDIR
fi
- echo "Running new incremental backup using $INCRBASEDIR as base."
- innobackupex --defaults-file=$MYCNF $USEROPTIONS $throttle $compress $compression_threads --incremental $TMPINCRDIR --incremental-basedir $INCRBASEDIR > $TMPFILE 2>&1
-else
- echo "Running new full backup."
- innobackupex --defaults-file=$MYCNF $USEROPTIONS $throttle $compress $compression_threads $FULLBACKUPDIR > $TMPFILE 2>&1
-fi
-{%- else %}
-# Get number of full and incremental backups
-NUMBER_OF_FULL=`find $FULLBACKUPDIR -maxdepth 1 -mindepth 1 -type d -print| wc -l`
-NUMBER_OF_INCR=`find $INCRBACKUPDIR -maxdepth 2 -mindepth 2 -type d -print| wc -l`
-echo "Number of Full backups stored: " $NUMBER_OF_FULL
-echo "Number of Incremental backups stored: " $NUMBER_OF_INCR
-echo "----------------------------"
-#If number of incremental mod number of full backups to keep equals 1, run full backup, otherwise run incremental
-if [ $(( ($NUMBER_OF_INCR + $NUMBER_OF_FULL) % ($INCRBEFOREFULL + 1) )) -eq 0 || FORCEFULL=true ] ; then
- echo "Running new full backup."
- innobackupex --defaults-file=$MYCNF $USEROPTIONS $compress $compression_threads $FULLBACKUPDIR > $TMPFILE 2>&1
-else
- # Create incremental backups dir if not exists.
- TMPINCRDIR=$INCRBACKUPDIR/$LATEST_FULL
- mkdir -p $TMPINCRDIR
-
- # Find latest incremental backup.
- LATEST_INCR=`find $TMPINCRDIR -mindepth 1 -maxdepth 1 -type d | sort -nr | head -1`
-
- # If this is the first incremental, use the full as base. Otherwise, use the latest incremental as base.
- if [ ! $LATEST_INCR ] ; then
- INCRBASEDIR=$FULLBACKUPDIR/$LATEST_FULL
- else
- INCRBASEDIR=$LATEST_INCR
+ # Space check
+ if [ $(df $BACKUPDIR | awk '{ print $5 }' | tail -n1 | cut -d '%' -f1) -gt 95 ]; then
+ error "There is not enough space on disk."
fi
- echo "Running new incremental backup using $INCRBASEDIR as base."
- innobackupex --defaults-file=$MYCNF $USEROPTIONS $compress $compression_threads --incremental $TMPINCRDIR --incremental-basedir $INCRBASEDIR > $TMPFILE 2>&1
-fi
-{%- endif %}
+}
+function backup()
+{
+ # Find latest full backup
+ LATEST_FULL="$(find $FULLBACKUPDIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1)"
+ # Get latest backup last modification time
+ LATEST_FULL_CREATED_AT="$(stat -c %Y $FULLBACKUPDIR/$LATEST_FULL)"
-if [ -z "`tail -1 $TMPFILE | grep 'completed OK!'`" ] ; then
- echo "$INNOBACKUPEX failed:"; echo
- echo "---------- ERROR OUTPUT from $INNOBACKUPEX ----------"
- cat $TMPFILE
- #rm -f $TMPFILE
- exit 1
-fi
+ # If compression is enabled, pass it on to the backup command
+ if [ "$compression" = True ]; then
+ compress="--compress"
+ compression_threads="--compress-threads=$compression_threads"
+ echo "Setting compression to True"
+ echo
+ else
+ compress=
+ compression_threads=
+ fi
-THISBACKUP=`awk -- "/Backup created in directory/ { split( \\\$0, p, \"'\" ) ; print p[2] }" $TMPFILE`
-#rm -f $TMPFILE
+ if [ "$BACKUPTIME"==false ]; then
+ # Run an incremental backup if latest full is still valid. Otherwise, run a new full one.
+ if [ "$LATEST_FULL" -a $(expr $LATEST_FULL_CREATED_AT + $FULLBACKUPLIFE + 5) -ge $STARTED_AT ] ; then
+ # Create incremental backups dir if not exists.
+ TMPINCRDIR="$INCRBACKUPDIR/$LATEST_FULL"
+ mkdir -p $TMPINCRDIR
-echo "Databases backed up successfully to: $THISBACKUP"
-echo
+ # Find latest incremental backup.
+ LATEST_INCR=$(find $TMPINCRDIR -mindepth 1 -maxdepth 1 -type d | sort -nr | head -1)
-# rsync just the new or modified backup files
-{%- if client.target is defined %}
-echo "Adding ssh-key of remote host to known_hosts"
-ssh-keygen -R {{ client.target.host }} 2>&1 | > $rsyncLog
-ssh-keyscan {{ client.target.host }} >> ~/.ssh/known_hosts 2>&1 | >> $rsyncLog
-echo "Rsyncing files to remote host"
-/usr/bin/rsync -rhtPv --rsync-path=rsync --progress $BACKUPDIR/* -e ssh xtrabackup@{{ client.target.host }}:$SERVERBACKUPDIR >> $rsyncLog
+ # If this is the first incremental, use the full as base. Otherwise, use the latest incremental as base.
+ if [ ! $LATEST_INCR ] ; then
+ INCRBASEDIR=$FULLBACKUPDIR/$LATEST_FULL
+ else
+ INCRBASEDIR=$LATEST_INCR
+ fi
-# Check if the rsync succeeded or failed
-if ! grep -q "rsync error: " $rsyncLog; then
- echo "Rsync to remote host completed OK"
-else
- echo "Rsync to remote host FAILED"
- exit 1
-fi
-{%- endif %}
+ echo "Running new incremental backup using $INCRBASEDIR as base."
+ innobackupex --defaults-file=$MYCNF $USEROPTIONS $throttle $compress $compression_threads --incremental $TMPINCRDIR --incremental-basedir $INCRBASEDIR 2>&1 | tee $TMPFILE
+ else
+ echo "Running new full backup."
+ innobackupex --defaults-file=$MYCNF $USEROPTIONS $throttle $compress $compression_threads $FULLBACKUPDIR 2>&1 | tee $TMPFILE
+ fi
+ else
+ # Get number of full and incremental backups
+ NUMBER_OF_FULL="$(find $FULLBACKUPDIR -maxdepth 1 -mindepth 1 -type d -print| wc -l)"
+ NUMBER_OF_INCR="$(find $INCRBACKUPDIR -maxdepth 2 -mindepth 2 -type d -print| wc -l)"
+ echo "Number of Full backups stored: " $NUMBER_OF_FULL
+ echo "Number of Incremental backups stored: " $NUMBER_OF_INCR
+ echo "----------------------------"
+ #If number of incremental mod number of full backups to keep equals 1, run full backup, otherwise run incremental
+ if [ $(( ($NUMBER_OF_INCR + $NUMBER_OF_FULL) % ($INCRBEFOREFULL + 1) )) -eq 0 || FORCEFULL=true ] ; then
+ echo "Running new full backup."
+ innobackupex --defaults-file=$MYCNF $USEROPTIONS $compress $compression_threads $FULLBACKUPDIR 2>&1 | tee $TMPFILE
+ else
+ # Create incremental backups dir if not exists.
+ TMPINCRDIR=$INCRBACKUPDIR/$LATEST_FULL
+ mkdir -p $TMPINCRDIR
+ # Find latest incremental backup.
+ LATEST_INCR=$(find $TMPINCRDIR -mindepth 1 -maxdepth 1 -type d | sort -nr | head -1)
-# Cleanup
-if [ $SKIPCLEANUP=false ] ; then
- {%- if client.backup_times is not defined %}
- echo "----------------------------"
- echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
- AGE=$(($FULLBACKUPLIFE * $KEEP / 60))
- find $FULLBACKUPDIR -maxdepth 1 -type d -mmin +$AGE -execdir echo "removing: "$FULLBACKUPDIR/{} \; -execdir rm -rf $FULLBACKUPDIR/{} \; -execdir echo "removing: "$INCRBACKUPDIR/{} \; -execdir rm -rf $INCRBACKUPDIR/{} \;
+ # If this is the first incremental, use the full as base. Otherwise, use the latest incremental as base.
+ if [ ! $LATEST_INCR ] ; then
+ INCRBASEDIR=$FULLBACKUPDIR/$LATEST_FULL
+ else
+ INCRBASEDIR=$LATEST_INCR
+ fi
+ echo "Running new incremental backup using $INCRBASEDIR as base."
+ innobackupex --defaults-file=$MYCNF $USEROPTIONS $compress $compression_threads --incremental $TMPINCRDIR --incremental-basedir $INCRBASEDIR 2>&1 | tee $TMPFILE
+ fi
+ fi
+ if [ -z "$(tail -1 $TMPFILE | grep 'completed OK!')" ] ; then
+ echo "$INNOBACKUPEX failed:"; echo
+ echo "---------- ERROR OUTPUT from $INNOBACKUPEX ----------"
+ cat $TMPFILE
+ exit 1
+ fi
+ THISBACKUP="$(awk -- "/Backup created in directory/ { split( \$0, p, \"'\" ) ; print p[2] }" $TMPFILE)"
+
+ echo "Databases backed up successfully to: $THISBACKUP"
echo
- echo "completed: `date`"
- exit 0
- {%- else %}
- echo "----------------------------"
- echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
- NUMBER_OF_FULL=$(( `find $FULLBACKUPDIR -maxdepth 1 -type d -print| wc -l` - 1))
- FULL_TO_DELETE=$(( $NUMBER_OF_FULL - $KEEP ))
- echo "Found $NUMBER_OF_FULL full backups and $KEEP should be kept. Thus $FULL_TO_DELETE will be deleted"
- if [ $FULL_TO_DELETE -gt 0 ] ; then
- cd $INCRBACKUPDIR
- ls -t $FULLBACKUPDIR | tail -n -$FULL_TO_DELETE | xargs -d '\n' rm -rf
- cd $FULLBACKUPDIR
- ls -t | tail -n -$FULL_TO_DELETE | xargs -d '\n' rm -rf
- else
- echo "There are less full backups than required, not deleting anything."
+
+ # rsync just the new or modified backup files
+ if [ ! -z "$SERVERBACKUPHOST" ]; then
+ echo "Adding ssh-key of remote host to known_hosts"
+ ssh-keygen -R $SERVERBACKUPHOST 2>&1 | tee $rsyncLog
+ ssh-keyscan $SERVERBACKUPHOST >> ~/.ssh/known_hosts 2>&1 | tee $rsyncLog
+ echo "Rsyncing files to remote host"
+ /usr/bin/rsync -rhtPpv --rsync-path=rsync --progress $BACKUPDIR/* -e ssh xtrabackup@$SERVERBACKUPHOST:$SERVERBACKUPDIR 2>&1 | tee $rsyncLog
+
+ # Check if the rsync succeeded or failed
+ if ! grep -q "rsync error: " $rsyncLog; then
+ echo "Rsync to remote host completed OK"
+ else
+ echo "Rsync to remote host FAILED"
+ exit 1
+ fi
fi
- {%- endif %}
-else
- echo "----------------------------"
- echo "--skip-cleanup parameter passed. Cleanup was not triggered"
-fi
+}
+function cleanup_backup()
+{
+ # Cleanup
+ if [ "$SKIPCLEANUP"==false ] ; then
+ if [ "$BACKUPTIME"==false ]; then
+ echo "----------------------------"
+ echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
+ AGE=$(($FULLBACKUPLIFE * $KEEP / 60))
+ find $FULLBACKUPDIR -maxdepth 1 -type d -mmin +$AGE -execdir echo "removing: "$FULLBACKUPDIR/{} \; -execdir rm -rf $FULLBACKUPDIR/{} \; -execdir echo "removing: "$INCRBACKUPDIR/{} \; -execdir rm -rf $INCRBACKUPDIR/{} \;
+
+ echo
+ echo "completed: $(date)"
+ exit 0
+ else
+ echo "----------------------------"
+ echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
+
+ NUMBER_OF_FULL="$(( $(find $FULLBACKUPDIR -maxdepth 1 -type d -print| wc -l) - 1))"
+ FULL_TO_DELETE="$(( $NUMBER_OF_FULL - $KEEP ))"
+ echo "Found $NUMBER_OF_FULL full backups and $KEEP should be kept. This $FULL_TO_DELETE will be deleted."
+ if [ $FULL_TO_DELETE -gt 0 ] ; then
+ cd $INCRBACKUPDIR
+ ls -t $FULLBACKUPDIR | tail -n -$FULL_TO_DELETE | xargs -d '\n' rm -rf
+ cd $FULLBACKUPDIR
+ ls -t | tail -n -$FULL_TO_DELETE | xargs -d '\n' rm -rf
+ else
+ echo "There are less full backups than required, not deleting anything."
+ fi
+ fi
+ else
+ echo "----------------------------"
+ echo "--skip-cleanup parameter passed. Cleanup was not triggered"
+ fi
+}
+
+prerequisites
+backup
+cleanup_backup
diff --git a/xtrabackup/files/innobackupex-server-restore-call.sh b/xtrabackup/files/innobackupex-server-restore-call.sh
index c12fed5..72fa8e3 100644
--- a/xtrabackup/files/innobackupex-server-restore-call.sh
+++ b/xtrabackup/files/innobackupex-server-restore-call.sh
@@ -1,34 +1,41 @@
{%- from "xtrabackup/map.jinja" import server with context %}
-#!/bin/sh
+#!/bin/bash
# This script returns appropriate backup that client will restore
+set -eo pipefail
-if [ $# -eq 0 ]; then
+BACKUPDIR="{{ server.backup_dir }}" # Backups base directory
+FULL="$(find $BACKUPDIR/full -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$1 | tail -1)"
+FULL_INCR="$(find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$1 | tail -1)"
+BEFORE_NEXT_FULL_INCR="$(find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$(( $1 - 1 )) | tail -1 || true)"
+
+function prerequisites(){
+ if [ $1 -eq 0 ]; then
echo "No arguments provided"
exit 1
-fi
+ fi
-# if arg is not an integer
-case $1 in
+ # if arg is not an integer
+ case $2 in
''|*[!0-9]*) echo "Argument must be integer"; exit 1 ;;
*) ;;
-esac
+ esac
+}
-BACKUPDIR={{ server.backup_dir }} # Backups base directory
-FULL=`find $BACKUPDIR/full -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$1 | tail -1`
-FULL_INCR=`find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$1 | tail -1`
-BEFORE_NEXT_FULL_INCR=`find $BACKUPDIR/incr -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -$(( $1 - 1 )) | tail -1`
-
-if [ -z "$BEFORE_NEXT_FULL_INCR" ]; then
+function return_backup(){
+ if [ -z "$BEFORE_NEXT_FULL_INCR" ]; then
BEFORE_NEXT_FULL_INCR="Empty"
-fi
+ fi
+ if [ $FULL = $FULL_INCR ]; then
+ LATEST_FULL_INCR=$(find $BACKUPDIR/incr/$FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1)
+ echo "$BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
+ elif [ $FULL = $BEFORE_NEXT_FULL_INCR ]; then
+ LATEST_FULL_INCR=$(find $BACKUPDIR/incr/$BEFORE_NEXT_FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1)
+ echo "$BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
+ else
+ echo "$BACKUPDIR/full/$FULL"
+ fi
+}
-if [ $FULL = $FULL_INCR ]; then
- LATEST_FULL_INCR=`find $BACKUPDIR/incr/$FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1`
- echo "$BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
-elif [ $FULL = $BEFORE_NEXT_FULL_INCR ]; then
- LATEST_FULL_INCR=`find $BACKUPDIR/incr/$BEFORE_NEXT_FULL_INCR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1 | tail -1`
- echo "$BACKUPDIR/incr/$FULL/$LATEST_FULL_INCR"
-else
- echo "$BACKUPDIR/full/$FULL"
-fi
+prerequisites "$#" "$1"
+return_backup
diff --git a/xtrabackup/files/innobackupex-server-runner.sh b/xtrabackup/files/innobackupex-server-runner.sh
index 3ff538a..5f9893d 100644
--- a/xtrabackup/files/innobackupex-server-runner.sh
+++ b/xtrabackup/files/innobackupex-server-runner.sh
@@ -1,47 +1,54 @@
{%- from "xtrabackup/map.jinja" import server with context %}
-#!/bin/sh
+#!/bin/bash
# The purpose of this script is to clean up unnecesary backups on a backup storage node (on xtrabackup server node)
-BACKUPDIR={{ server.backup_dir }} # Backups base directory
-FULLBACKUPDIR=$BACKUPDIR/full # Full backups directory
-INCRBACKUPDIR=$BACKUPDIR/incr # Incremental backups directory
-KEEP={{ server.full_backups_to_keep }} # Number of full backups (and its incrementals) to keep
+set -eo pipefail
+
+BACKUPDIR="{{ server.backup_dir }}" # Backups base directory
+KEEP="{{ server.full_backups_to_keep }}" # Number of full backups (and its incrementals) to keep
{%- if server.backup_times is defined %}
-INCRBEFOREFULL={{ server.incr_before_full }}
-KEEPINCR=$(( $INCRBEFOREFULL * KEEP ))
+INCRBEFOREFULL="{{ server.incr_before_full }}"
+KEEPINCR="$(( $INCRBEFOREFULL * KEEP ))"
{%- else %}
-HOURSFULLBACKUPLIFE={{ server.hours_before_full }} # Lifetime of the latest full backup in hours
-FULLBACKUPLIFE=$(( $HOURSFULLBACKUPLIFE * 60 * 60 ))
+HOURSFULLBACKUPLIFE="{{ server.hours_before_full }}" # Lifetime of the latest full backup in hours
+FULLBACKUPLIFE="$(( $HOURSFULLBACKUPLIFE * 60 * 60 ))"
{%- endif %}
+{%- if server.backup_times is defined %}
+BACKUPTIME="true"
+{%- endif %}
+FULLBACKUPDIR="$BACKUPDIR/full" # Full backups directory
+INCRBACKUPDIR="$BACKUPDIR/incr" # Incremental backups directory
# Cleanup
-{%- if server.backup_times is not defined %}
-echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
-AGE=$(($FULLBACKUPLIFE * $KEEP / 60))
-find $FULLBACKUPDIR -maxdepth 1 -type d -mmin +$AGE -execdir echo "removing: "$FULLBACKUPDIR/{} \; -execdir rm -rf $FULLBACKUPDIR/{} \; -execdir echo "removing: "$INCRBACKUPDIR/{} \; -execdir rm -rf $INCRBACKUPDIR/{} \;
+function cleanup(){
+ if [ $BACKUPTIME==false ]; then
+ echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
+ AGE=$(($FULLBACKUPLIFE * $KEEP / 60))
+ find $FULLBACKUPDIR -maxdepth 1 -type d -mmin +$AGE -execdir echo "removing: "$FULLBACKUPDIR/{} \; -execdir rm -rf $FULLBACKUPDIR/{} \; -execdir echo "removing: "$INCRBACKUPDIR/{} \; -execdir rm -rf $INCRBACKUPDIR/{} \;
+ echo "completed: $(date)"
+ exit 0
+ else
+ echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
+ NUMBER_OF_FULL=$(( $(find $FULLBACKUPDIR -maxdepth 1 -type d -print| wc -l) - 1))
+ NUMBER_OF_INCR=$(( $(find $INCRBACKUPDIR -maxdepth 2 -type d -print| wc -l) - 1))
+ FULL_TO_DELETE=$(( $NUMBER_OF_FULL - $KEEP ))
+ INCR_TO_DELETE=$(( $NUMBER_OF_INCR - $KEEPINCR ))
+ echo "Found $NUMBER_OF_FULL full backups and $KEEP should be kept. Thus $FULL_TO_DELETE will be deleted"
+ echo "Found $NUMBER_OF_INCR full backups and $KEEPINCR should be kept. Thus $INCR_TO_DELETE will be deleted"
+ if [ $FULL_TO_DELETE -gt 0 ] ; then
+ cd $FULLBACKUPDIR
+ ls -t | tail -n -$FULL_TO_DELETE | xargs -d '\n' rm -rf
+ else
+ echo "There are less full backups than required, not deleting anything."
+ fi
+ if [ $INCR_TO_DELETE -gt 0 ] ; then
+ cd $INCRBACKUPDIR
+ ls -t | tail -n -$INCR_TO_DELETE | xargs -d '\n' rm -rf
+ else
+ echo "There are less incremental backups than required, not deleting anything."
+ fi
+ fi
+}
-echo
-echo "completed: `date`"
-exit 0
-{%- else %}
-echo "Cleanup. Keeping only $KEEP full backups and its incrementals."
-NUMBER_OF_FULL=$(( `find $FULLBACKUPDIR -maxdepth 1 -type d -print| wc -l` - 1))
-NUMBER_OF_INCR=$(( `find $INCRBACKUPDIR -maxdepth 2 -type d -print| wc -l` - 1))
-FULL_TO_DELETE=$(( $NUMBER_OF_FULL - $KEEP ))
-INCR_TO_DELETE=$(( $NUMBER_OF_INCR - $KEEPINCR ))
-echo "Found $NUMBER_OF_FULL full backups and $KEEP should be kept. Thus $FULL_TO_DELETE will be deleted"
-echo "Found $NUMBER_OF_INCR full backups and $KEEPINCR should be kept. Thus $INCR_TO_DELETE will be deleted"
-if [ $FULL_TO_DELETE -gt 0 ] ; then
-cd $FULLBACKUPDIR
-ls -t | tail -n -$FULL_TO_DELETE | xargs -d '\n' rm -rf
-else
-echo "There are less full backups than required, not deleting anything."
-fi
-if [ $INCR_TO_DELETE -gt 0 ] ; then
-cd $INCRBACKUPDIR
-ls -t | tail -n -$INCR_TO_DELETE | xargs -d '\n' rm -rf
-else
-echo "There are less incremental backups than required, not deleting anything."
-fi
-{%- endif %}
\ No newline at end of file
+cleanup