#!/usr/bin/env bash CUR_IFS="$IFS" script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="$(dirname "${working_dir}")/conf/${script_name%%.*}.conf" log_file="$(mktemp)" backup_date=$(date +%Y-%m-%d-%H%M) # ============= # --- Some Variable # ============= right_tabstop=75 # ============= # --- Some functions # ============= usage() { [[ -n "$1" ]] && error "$1" [[ $terminal ]] && echo -e " \033[1mUsage:\033[m $(basename $0) [OPTION [OPTION .. \033[1mDescription\033[m Script restores a website from backup system. \033[1mOptions\033[m -b Sets batch mode to true - no interaction will be made. -d Name of database concerning to the restoring website. -h Prints this help. -s The (backuped) server holding the production website. -t The backup date. -w the website \033[1mFiles\033[m Configuration file: $conf_file \033[1mExample:\033[m Restore website 'cloud-01.oopen.de' from server 'cl-01.oopen.de' at 11/24/2020 (24 November 2020). Run in batch mode. \033[1m$(basename $0) -b -d cloud_01 -s cl-01.oopen.de -t 2020-11-24 -w cloud-01.oopen.de\033[m " clean_up 1 } clean_up() { if [[ -f "$_backup_crontab_file" ]]; then blank_line echononl " (Re)Install Crontab from previously saved crontab file '$_backup_crontab_file'.." crontab $_backup_crontab_file >> $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi fi if [[ -n "$CUR_AUTOCOMMIT" ]] ; then mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL autocommit='$CUR_AUTOCOMMIT'" > /dev/null 2>&1 fi if [[ -n "$CUR_FOREIGN_KEY_CHECKS" ]] ; then mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL autocommit='$CUR_FOREIGN_KEY_CHECKS'" > /dev/null 2>&1 fi if [[ -n "$CUR_UNIQUE_CHECKS" ]] ; then mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL autocommit='$CUR_UNIQUE_CHECKS'" > /dev/null 2>&1 fi if [[ -n "$CUR_INNODB_FLUSH_LOG_AT_TRX_COMMIT" ]] ; then mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL autocommit='$CUR_INNODB_FLUSH_LOG_AT_TRX_COMMIT'" > /dev/null 2>&1 fi # Perform program exit housekeeping rm -f $log_file blank_line exit $1 } is_number() { return $(test ! -z "${1##*[!0-9]*}" > /dev/null 2>&1); # - also possible # - #[[ ! -z "${1##*[!0-9]*}" ]] && return 0 || return 1 #return $([[ ! -z "${1##*[!0-9]*}" ]]) } echononl(){ if $terminal ; then echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n "$*\\c" 1>&2 else echo -e -n "$*" 1>&2 fi rm /tmp/shprompt$$ fi } echo_done() { if $terminal ; then echo -e "\033[${right_tabstop}G[ \033[32mdone\033[m ]" fi } echo_ok() { if $terminal ; then echo -e "\033[${right_tabstop}G[ \033[32mok\033[m ]" fi } echo_warning() { if $terminal ; then echo -e "\033[${right_tabstop}G[ \033[33m\033[1mwarn\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[${right_tabstop}G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[${right_tabstop}G[ \033[37mskipped\033[m ]" fi } fatal (){ blank_line if $terminal ; then echo -e "\t[ \033[31m\033[1mFatal\033[m ]: \033[37m\033[1m$*\033[m" echo "" echo -e "\t\033[31m\033[1m Script will be interrupted..\033[m\033[m" else echo "fatal: $*" echo "Script will be interrupted.." fi clean_up 1 } error(){ blank_line if $terminal ; then echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*" else echo "Error: $*" fi blank_line } warn (){ blank_line if $terminal ; then echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" else echo "Warning: $*" fi blank_line } info (){ if $terminal ; then echo "" echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*" echo "" fi } time_duration () { local __begin=$1 local __end=$2 local __duration if [[ "$__begin" ]] && [[ "$__end" ]] ; then local __duration local __time=`expr $__end - $__begin` local __t_h=`expr $__time / 60 / 60` local __t_rest_h=`expr $__time - $__t_h \\* 60 \\* 60` local __t_m=`expr $__t_rest_h / 60` local __t_s=`expr $__t_rest_h - $__t_m \\* 60` if [[ $__t_h -gt 0 ]]; then if [[ $__t_h -lt 10 ]] ; then __t_h=" $__t_h" fi if [[ $__t_m -lt 10 ]] ; then __t_m=" $__t_m" fi if [[ $__t_s -lt 10 ]] ; then __t_s=" $__t_s" fi echo "$__t_h h : $__t_m min : $__t_s sec" elif [[ $__t_m -gt 0 ]]; then if [[ $__t_m -lt 10 ]] ; then __t_m=" $__t_m" fi if [[ $__t_s -lt 10 ]] ; then __t_s=" $__t_s" fi echo "$__t_m min : $__t_s sec" else if [[ $__t_s -lt 10 ]] ; then echo " $__t_s sec" else echo "$__t_s sec" fi fi else echo "N/A" fi } echo_duration () { local __time_duration=${1} local __length=${#__time_duration} # print duratuion inside inside square brackets "[ duration ]" with blank delimiter, # so add reduce tabstop by 4 characters # __tabstop=`expr ${right_tabstop} - ${__length} - 1 - 4` echo -en "\033[${__tabstop}G[ \033[33m${__time_duration}\033[m ]" } detect_mysql_version () { _MYSQLD_VERSION="$(mysqld -V 2>/dev/null)" if [[ -z "$_MYSQLD_VERSION" ]]; then fatal "No installed MySQL server or distribution found!" elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ percona- ]]; then MYSQL_CUR_DISTRIBUTION="Percona" elif [[ "$_MYSQLD_VERSION" =~ MariaDB ]]; then MYSQL_CUR_DISTRIBUTION="MariaDB" elif [[ "$_MYSQLD_VERSION" =~ MySQL ]]; then MYSQL_CUR_DISTRIBUTION="MySQL" elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mysql- ]]; then MYSQL_CUR_DISTRIBUTION="MySQL" elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mariadb- ]]; then MYSQL_CUR_DISTRIBUTION="MariaDB" else error "MySQL Instalation found, but cannot determin the distribution!" MYSQL_CUR_DISTRIBUTION= echo "" echo " Select the MySQL distribution to install." echo "" echo " [1] MySQL (the original community edition)" echo " [2] Percona Server for MySQL" echo " [3] MariaDB" echo "" echononl " Eingabe [1/2/3]: " while [ "$MYSQL_CUR_DISTRIBUTION" != "MySQL" -a "$MYSQL_CUR_DISTRIBUTION" != "MariaDB" -a "$MYSQL_CUR_DISTRIBUTION" != "Percona" ];do read OPTION case $OPTION in 1) MYSQL_CUR_DISTRIBUTION="MySQL" ;; 2) MYSQL_CUR_DISTRIBUTION="Percona" ;; 3) MYSQL_CUR_DISTRIBUTION="MariaDB" ;; *) echo "" echo -e "\tFalsche Eingabe ! [ 1 = MySQL ; 2 = Percona ; 3 = MariaDB ]" echo "" echononl " Eingabe:" ;; esac done fi MYSQL_VERSION="$(echo $_MYSQLD_VERSION | grep -o -E "[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?" | head -n 1)" MYSQL_MAJOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1)" MYSQL_MINOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f2)" MYSQL_PATCH_LEVEL="$(echo $MYSQL_VERSION | cut -d '.' -f3)" MYSQL_MAIN_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1,2)" } ## - Check if a given array (parameter 2) contains a given string (parameter 1) ## - containsElement () { local e for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done return 1 } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } blank_line() { if $terminal ; then echo "" fi } # ---------- # - Jobhandling # ---------- # - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM # - trap clean_up SIGHUP SIGINT SIGTERM # ============= # --- Some # ============= # - Support systemd ? # - if [[ "X$(which systemd)" = "X" ]]; then SYSTEMD_EXISTS=false else SYSTEMD_EXISTS=true fi # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else terminal=false fi #clear if $terminal ; then echo "" echo -e "\033[32m-----\033[m" echo "Configure Recovery Cloud System from Backup" echo -e "\033[32m-----\033[m" fi # ---------- # Read Configurations from $conf_file # ---------- # - Give your default values here # - BATCH_MODE=false IS_NEXTCLOUD=false DEFAULT_BACKUP_BASE_DIR="/backup" DEFAULT_DATABASE_TYPE="mysql" DEFAULT_MYSQL_CREDENTIAL_ARGS="--defaults-file=/usr/local/mysql/sys-maint.cnf" # Note: # HTTP_USER/HTTP_GROUP from this backup machine! # DEFAULT_HTTP_USER="www-data" DEFAULT_HTTP_GROUP="www-data" DEFAULT_PHP_ENGINE="FPM" DEFAULT_LOCAL_WEBSITE_BASE_DIR="/var/www" blank_line echononl " Include Configuration file.." if [[ ! -f $conf_file ]]; then echo_skipped warn "No configuration file '$conf_file' found!\n Loading default values.." else source $conf_file echo_done fi blank_line # ---------- # - Read commandline parameter # ---------- while getopts bd:hs:t:w: opt ; do case $opt in b) BATCH_MODE=true ;; d) DATABASE_NAME="$OPTARG" ;; h) usage ;; s) SERVER="$OPTARG" ;; t) BACKUP_DATE="$OPTARG" ;; w) WEBSITE="$OPTARG" ;; \?) usage ;; esac done [[ -z "$DATABASE_TYPE" ]] && DATABASE_TYPE="$DEFAULT_DATABASE_TYPE" #[[ -z "$MYSQL_CREDENTIAL_ARGS" ]] && MYSQL_CREDENTIAL_ARGS="$DEFAULT_MYSQL_CREDENTIAL_ARGS" if [[ -z "$MYSQL_CREDENTIAL_ARGS" ]] ; then detect_mysql_version MAJOR_VERSION="$MYSQL_MAJOR_VERSION" MINOR_VERSION="$MYSQL_MINOR_VERSION" PATCH_LEVEL="$MYSQL_PATCH_LEVEL" if [[ "$MYSQL_CUR_DISTRIBUTION" = "MariaDB" ]] && ([[ $MAJOR_VERSION -gt 10 ]] \ || ( [[ $MAJOR_VERSION -eq 10 ]] && [[ $MINOR_VERSION -gt 3 ]] )) ; then if [[ -S "/tmp/mysql.sock" ]]; then MYSQL_CREDENTIAL_ARGS="-u root -S /tmp/mysql.sock" elif [[ -S "/run/mysqld/mysqld.sock" ]]; then MYSQL_CREDENTIAL_ARGS="-u root -S /run/mysqld/mysqld.sock" elif [[ -S "/var/run/mysqld/mysqld.sock" ]]; then MYSQL_CREDENTIAL_ARGS="-u root -S /var/run/mysqld/mysqld.sock" else fatal "Parameter 'MYSQL_CREDENTIAL_ARGS' cannot be determined automated. Use configuration file "$conf_file" to set parameter manually." fi else if $(mysql --login-path=local -e ";" > /dev/null 2>&1) ; then MYSQL_CREDENTIAL_ARGS="--login-path=local" elif [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then MYSQL_CREDENTIAL_ARGS="--defaults-file=/usr/local/mysql/sys-maint.cnf" elif [[ -f "/etc/mysql/debian.cnf" ]] ; then MYSQL_CREDENTIAL_ARGS="--defaults-file=/etc/mysql/debian.cnf" else fatal "Parameter 'MYSQL_CREDENTIAL_ARGS' cannot be determined automated. Use configuration file "$conf_file" to set parameter manually." fi fi fi [[ -z "$BACKUP_BASE_DIR" ]] && BACKUP_BASE_DIR="$DEFAULT_BACKUP_BASE_DIR" if [[ ! -d "$BACKUP_BASE_DIR" ]] ; then fatal "Backup Base Directory (${BACKUP_BASE_DIR}) NOT found!" fi [[ -z "$LOCAL_WEBSITE_BASE_DIR" ]] && LOCAL_WEBSITE_BASE_DIR="$DEFAULT_LOCAL_WEBSITE_BASE_DIR" [[ -z "$PHP_ENGINE" ]] && PHP_ENGINE="$DEFAULT_PHP_ENGINE" # Check PHP Version # PHP_VERSION="" if [[ "$PHP_ENGINE" = "FPM" ]] ; then if [[ -z "$PHP_VERSION" ]] ; then if [[ -h "/usr/local/php" ]]; then PHP_VERSION="$(realpath /usr/local/php | cut -d'-' -f2 | cut -d'.' -f1,2)" fi fi fi # - Determin PHP binary # - php_binary="$(realpath "$(which php)")" if [[ -z "$php_binary" ]]; then if [[ -x "/usr/local/php/bin/php" ]]; then php_binary="/usr/local/php/bin/php" else fatal "No PHP binary present" fi else if [[ ! -x "$php_binary" ]]; then fatal "Found PHP binary '$php_binary', but this file is not executable!" fi fi # - Determin user/group of the webserver # - httpd_binary="`which httpd`" if [ -z "$httpd_binary" ]; then httpd_binary="$(ps -axu | grep httpd | grep -e "^root" | grep -v grep | awk '{print$11}')" if [ -z "$httpd_binary" ]; then if [ -x "/usr/local/apache2/bin/httpd" ]; then httpd_binary="/usr/local/apache2/bin/httpd" fi fi fi if [ -x "$httpd_binary" ];then # - Determin websever user # - _HTTP_USER="`$httpd_binary -t -D DUMP_RUN_CFG 2> /dev/null | grep -i -e "^User" | awk '{print$2}' | cut -d\"=\" -f2 | tr -d '"'`" > /dev/null 2>&1 _HTTP_GROUP="`$httpd_binary -t -D DUMP_RUN_CFG 2> /dev/null | grep -i -e "^Group" | awk '{print$2}' | cut -d\"=\" -f2 | tr -d '"'`" > /dev/null 2>&1 # - Is webserver running ? # - PID=$(ps aux | grep "$(realpath $httpd_binary)" | grep -e "^root" | grep -v grep | awk '{print$2}') if [[ "X${PID}X" = "XX" ]] ;then IS_HTTPD_RUNNING=false else IS_HTTPD_RUNNING=true fi fi if [[ -n "$_HTTP_USER" ]] ; then if [[ -n "$HTTP_USER" ]] && [[ "$_HTTP_USER" != "$HTTP_USER" ]]; then warn "The script has determined \033[1;37m${_HTTP_USER}\033[m as Webservers user. This\n value differs from the value given in your configuration file, \n which is \033[1;37m${HTTP_USER}\033[m and takes precedence." else HTTP_USER=$_HTTP_USER fi else [[ -n "$HTTP_USER" ]] || HTTP_USER=$DEFAULT_HTTP_USER fi if [[ -n "$_HTTP_GROUP" ]] ; then if [[ -n "$HTTP_GROUP" ]] && [[ "$_HTTP_GROUP" != "$HTTP_GROUP" ]]; then warn "The script has determined \033[1;37m${_HTTP_GROUP}\033[m as Webservers group. This\n value differs from the value given in your configuration file, \n which is \033[1;37m${HTTP_GROUP}\033[m and takes precedence." else HTTP_GROUP=$_HTTP_GROUP fi else [[ -n "$HTTP_GROUP" ]] || HTTP_GROUP=$DEFAULT_HTTP_GROUP fi # ---------- # - Read in parameters from command line # ---------- if $terminal && ! $BATCH_MODE ; then declare -a unsorted_server_arr declare -a server_arr declare -a unsorted_version_arr declare -a version_arr declare -a unsorted_website_arr declare -a website_arr # Get list (array) of backuped servers # while IFS='' read -r -d '' _server_backuped ; do [[ "$(basename "$_server_backuped")" = "www" ]] && continue [[ "$(basename "$_server_backuped")" = "lost+found" ]] && continue unsorted_server_arr+=("$(basename "$_server_backuped")") done < <(find "${BACKUP_BASE_DIR}" -mindepth 1 -maxdepth 1 -type d -print0) # - Sort array # - IFS=$'\n' server_arr=($(sort <<<"${unsorted_server_arr[*]}")) IFS="$CUR_IFS" SERVER= _OK=false echo "" echo "From which Server would you like to restore?" echo "" declare -i i=0 for _server in ${server_arr[@]} ; do IFS=':' read -a _arr <<< ${_server} echo " [$i] ${_arr[0]}" ((i++)) done echo echononl " Eingabe: " while ! $_OK ; do read _IN if is_number "$_IN" && [[ -n ${server_arr[$_IN]} ]]; then IFS=':' read -a _arr <<< ${server_arr[$_IN]} SERVER=${_arr[0]} _OK=true else echo "" echo -e "\tFalsche Eingabe !" echo "" echononl " Eingabe: " fi done for _dir in $(ls "${BACKUP_BASE_DIR}/${SERVER}/archive/") ; do [[ -d "${BACKUP_BASE_DIR}/${SERVER}/archive/$_dir" ]] || continue _backup_date="$(echo "$_dir"| grep -o -E "[0-9]{4}-[0-9]{2}-[0-9]{2}")" unsorted_version_arr+=("$(basename "${_dir}"):${_backup_date}") done if [[ ${#unsorted_version_arr[@]} -lt 1 ]] ; then fatal "No backuped version present!" fi # - Sort array # - IFS=$'\n' version_arr=($(sort <<<"${unsorted_version_arr[*]}")) IFS="$CUR_IFS" RESTORE_DIR="" BACKUP_DATE="" _OK=false echo "" echo "Which version would you like to restore?" echo "" declare -i i=0 for _backup_version in ${version_arr[@]} ; do IFS=':' read -a _arr <<< ${_backup_version} #echo " [$i] Directory ${_arr[0]} Version from ${_arr[1]}" echo -e " [$i] Backup Version from \033[1m${_arr[1]}\033[m" ((i++)) done echo echononl " Eingabe: " while ! $_OK ; do read _IN if is_number "$_IN" && [[ -n ${version_arr[$_IN]} ]]; then IFS=':' read -a _arr <<< ${version_arr[$_IN]} BACKUP_DIR="${BACKUP_BASE_DIR}/${SERVER}/archive/${_arr[0]}" BACKUP_DATE="${_arr[1]}" _OK=true else echo "" echo -e "\tFalsche Eingabe !" echo "" echononl " Eingabe: " fi done if [[ -d "${BACKUP_DIR}/misc/www" ]]; then DEFAULT_WEBSITE_BASE_DIR="${BACKUP_DIR}/misc/www" elif [[ -d "${BACKUP_DIR}/data/www" ]]; then DEFAULT_WEBSITE_BASE_DIR="${BACKUP_DIR}/data/www" elif [[ -d "${BACKUP_DIR}/backup/www" ]]; then DEFAULT_WEBSITE_BASE_DIR="${BACKUP_DIR}/backup/www" elif [[ -d "${BACKUP_DIR}/var/www" ]] ;then DEFAULT_WEBSITE_BASE_DIR="${BACKUP_DIR}/var/www" else DEFAULT_WEBSITE_BASE_DIR="" fi WEBSITE_BASE_DIR="" echo "" echo -e "\033[32m--\033[m" echo "" echo -e "Give Website Base Directory of the machine \033[1m${SERVER}\033[m" echo "" echo "" if [[ -n "${DEFAULT_WEBSITE_BASE_DIR}" ]]; then while [[ "X${WEBSITE_BASE_DIR}" = "X" ]]; do echononl " Website Base Directory[${DEFAULT_WEBSITE_BASE_DIR}]: " read WEBSITE_BASE_DIR if [ "X${WEBSITE_BASE_DIR}" = "X" ]; then WEBSITE_BASE_DIR="${DEFAULT_WEBSITE_BASE_DIR}" fi if [[ ! -d "${WEBSITE_BASE_DIR}" ]]; then echo -e "\n\t Website Base Directory\033[33m\033[1m${RESTORE_DIR}\033[m does not exist!\n" WEBSITE_BASE_DIR="" fi done else while [[ "X${WEBSITE_BASE_DIR}" = "X" ]]; do echononl " Website Base Directory: " read WEBSITE_BASE_DIR if [ "X${WEBSITE_BASE_DIR}" = "X" ]; then echo -e "\n\t\033[33m\033[1mWebsite Base Directory is required!\033[m\n" continue fi if [[ ! -d "${WEBSITE_BASE_DIR}" ]]; then echo -e "\n\tGiven Website Base Directory \033[33m\033[1m${WEBSITE_BASE_DIR}\033[m does not exist!\n" WEBSITE_BASE_DIR="" fi done fi # Get list (array) of Websites # while IFS='' read -r -d '' _website ; do [[ "$(basename "$_website")" = "lost+found" ]] && continue [[ "$(basename "$_website")" = "default" ]] && continue [[ "$(basename "$_website")" = "dehydrated" ]] && continue unsorted_website_arr+=("$(basename "$_website")") done < <(find "${WEBSITE_BASE_DIR}" -mindepth 1 -maxdepth 1 -type d -print0) if [[ ${#unsorted_website_arr} -eq 0 ]]; then fatal "No backuped website found at '${WEBSITE_BASE_DIR}'!" fi # - Sort array # - IFS=$'\n' website_arr=($(sort <<<"${unsorted_website_arr[*]}")) IFS="$CUR_IFS" WEBSITE= _OK=false echo "" echo "Which site would you like to restore?" echo "" declare -i i=0 for _site in ${website_arr[@]} ; do IFS=':' read -a _arr <<< ${_site} echo " [$i] ${_arr[0]}" ((i++)) done echo echononl " Eingabe: " while ! $_OK ; do read _IN if is_number "$_IN" && [[ -n ${website_arr[$_IN]} ]]; then WEBSITE=${website_arr[$_IN]} _OK=true else echo "" echo -e "\tFalsche Eingabe !" echo "" echononl " Eingabe: " fi done RESTORE_DIR="${WEBSITE_BASE_DIR}/${WEBSITE}" if [[ "$(basename $(realpath "${RESTORE_DIR}/htdocs"))" =~ ^nextcloud ]]; then NC_RESTORE_VERSION="$(basename $(realpath "${RESTORE_DIR}/htdocs") | cut -d"-" -f2)" IS_NEXTCLOUD=true fi DATABASE_NAME="" echo "" echo -e "\033[32m--\033[m" echo "" echo "Insert Database name for .." echo "" echo "" echononl "Database name: " read _DATABASE_NAME while [ "X$(trim "$_DATABASE_NAME")" = "X" ] ; do echo -e "\n\t\033[33m\033[1mEingabe erforderlich.\033[m\n" echononl "Database name: " read _DATABASE_NAME done DATABASE_NAME="$(trim "$_DATABASE_NAME")" else if [[ -z "$SERVER" ]]; then fatal "No Server (Parameter '-s') given!" fi if [[ -z "$BACKUP_DATE" ]] ; then fatal "No Backup date (Parameter '-t') given!" else BACKUP_DIR="${BACKUP_BASE_DIR}/${SERVER}/archive/Backup_${BACKUP_DATE}" WEBSITE_BASE_DIR="${BACKUP_DIR}/var/www" fi if [[ -z "${WEBSITE}" ]]; then fatal "No Website (Parameter '-w') given!" else RESTORE_DIR="${WEBSITE_BASE_DIR}/${WEBSITE}" NC_RESTORE_VERSION="$(basename $(realpath "${RESTORE_DIR}/htdocs") | cut -d"-" -f2)" fi if [[ -z "$DATABASE_NAME" ]] ; then fatal "No Website (Parameter '-d') given!" fi fi # ============= # --- Some final checks # ============= if ! $(ls /backup/${SERVER}/MySQL/${DATABASE_NAME}/${DATABASE_NAME}-${BACKUP_DATE}-* > /dev/null 2>&1) ; then if ! $(ls /backup/${SERVER}/MariaDB/${DATABASE_NAME}/${DATABASE_NAME}-${BACKUP_DATE}-* > /dev/null 2>&1) ; then fatal "No backuped database '${DATABASE_NAME} found!" else SQL_FILE="$(ls /backup/${SERVER}/MariaDB/${DATABASE_NAME}/${DATABASE_NAME}-${BACKUP_DATE}-* | head -n 1)" fi else SQL_FILE="$(ls /backup/${SERVER}/MariaDB/${DATABASE_NAME}/${DATABASE_NAME}-${BACKUP_DATE}-* | head -n 1)" fi if [[ ! -d "$WEBSITE_BASE_DIR" ]]; then fatal "Websites base directory "${WEBSITE_BASE_DIR}" not present" fi if $terminal ; then echo "" echo "" echo -e "\033[32m--\033[m" echo -e "\033[1;32mRecover \033[1;37m${WEBSITE}\033[1;32m from \033[1;37m${BACKUP_DATE}\033[1;32m - Start with Parameters:" echo -e "\033[32m--\033[m" echo "" echo -e " Server from which site will be restored....: $SERVER" echo "" echo -e " Website to restore.........................: $WEBSITE" echo "" echo -e " Backup base directory......................: $BACKUP_BASE_DIR" echo -e " Local Website Base Directory...............: $LOCAL_WEBSITE_BASE_DIR" echo "" if $IS_NEXTCLOUD ; then echo -e " Version of backuped nextcloud..............: $NC_RESTORE_VERSION" echo "" fi #echo -e " Backup Host Directory......................: $BACKUP_DIR" echo -e " Restore Directory..........................: $RESTORE_DIR" echo -e " Backup date ...............................: $BACKUP_DATE" echo "" echo -e " Database type..............................: $DATABASE_TYPE" echo -e " Databse name...............................: $DATABASE_NAME" echo -e " SQL File Path..............................: $SQL_FILE" echo "" echo -e " Webserver user.............................: $HTTP_USER" echo -e " Webserver group............................: $HTTP_GROUP" echo "" if [[ -n "$PHP_VERSION" ]]; then echo -e " PHP version................................: $PHP_VERSION" echo -e " PHP Engine.................................: $PHP_ENGINE" echo "" fi if [[ "$DATABASE_TYPE" = "mysql" ]] ; then echo -e " Mysql Credentials..........................: $MYSQL_CREDENTIAL_ARGS" fi echo "" echo "" echo -n " Type upper case 'YES' to continue executing with this parameters: " read OK if [[ "$OK" = "YES" ]] ; then echo "" echo "" echo -e "\033[1;32mLet's go\033[1;37m..\033[m" else fatal "Abort by user request - Answer as not 'YES'" fi fi # ----- # - Doing some pre-script tasks # ----- if $terminal ; then echo "" echo "" echo -e "\033[37m\033[1mDoing some pre-script tasks..\033[m" echo "" fi # - Deaktiviere Cronjobs # - _backup_crontab_file=/tmp/crontab_root.${backup_date} echononl " Backup Crontab to '$_backup_crontab_file'" crontab -l > $_backup_crontab_file 2> $log_file if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi echononl " Remove crontab for root.." crontab -r > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi # - Stop Apache Webserver # - blank_line echononl " Stop Apache Webserver.." if $SYSTEMD_EXISTS ; then systemctl stop apache2 if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else /etc/init.d/apache2 stop if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi fi blank_line echononl " Create Directory '$BACKUP_BASE_DIR'.." if [[ ! -d "$BACKUP_BASE_DIR" ]]; then mkdir -p "$BACKUP_BASE_DIR" > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else echo_skipped fi blank_line # - GET current (global) Autocommit value # - echononl " GET current (global) value \033[1mautocommit\033[m" CUR_AUTOCOMMIT="$(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SHOW GLOBAL VARIABLES LIKE 'autocommit'" | awk '{print$2}')" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi # - GET current (global) value for 'foreign_key_checks' # - echononl " GET current (global) value \033[1mforeign_key_checks\033[m" CUR_FOREIGN_KEY_CHECKS="$(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SHOW GLOBAL VARIABLES LIKE 'foreign_key_checks'" | awk '{print$2}')" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi # - GET current (global) value for 'unique_checks' # - echononl " GET current (global) value \033[1munique_checks\033[m" CUR_UNIQUE_CHECKS="$(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SHOW GLOBAL VARIABLES LIKE 'unique_checks'" | awk '{print$2}')" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi # - GET current (global) value for 'innodb_flush_log_at_trx_commit' # - echononl " GET current (global) value \033[1minnodb_flush_log_at_trx_commit\033[m" CUR_INNODB_FLUSH_LOG_AT_TRX_COMMIT="$(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SHOW GLOBAL VARIABLES LIKE 'innodb_flush_log_at_trx_commit'" | awk '{print$2}')" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi blank_line echononl " Set Autocommit to OFF" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL autocommit='OFF'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Set foreign_key_checks to OFF" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL foreign_key_checks='OFF'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Set unique_checks to OFF" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL unique_checks='OFF'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Set innodb_flush_log_at_trx_commit to 2" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL innodb_flush_log_at_trx_commit=2" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi # ----- # - Main Part of Script # ----- if $terminal ; then echo "" echo "" echo -e "\033[37m\033[1mMain Part of Script.\033[m" echo "" fi echononl " Remove Documentroot Directory if exists .." if [[ -d "${LOCAL_WEBSITE_BASE_DIR}/$(basename "$RESTORE_DIR")" ]] ; then b_timestamp=$(date +"%s") rm -rf "${LOCAL_WEBSITE_BASE_DIR}/$(basename "$RESTORE_DIR")" > $log_file 2>&1 retval=$? e_timestamp=$(date +"%s") echo_duration "$(time_duration $b_timestamp $e_timestamp)" if [[ $retval -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else echo_skipped fi blank_line echononl " Set Autocommit to OFF" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL autocommit='OFF'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Set foreign_key_checks to OFF" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL foreign_key_checks='OFF'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Set unique_checks to OFF" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL unique_checks='OFF'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Set innodb_flush_log_at_trx_commit to 2" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL innodb_flush_log_at_trx_commit=2" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi blank_line echononl " Restore Database '${DATABASE_NAME}'.." b_timestamp=$(date +"%s") mysql $MYSQL_CREDENTIAL_ARGS $DATABASE_NAME < $SQL_FILE > $log_file 2>&1 retval=$? e_timestamp=$(date +"%s") echo_duration "$(time_duration $b_timestamp $e_timestamp)" if [[ $retval -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi blank_line echononl " Sync Webspace - site '${WEBSITE}'.." # Begin timestamp # b_timestamp=$(date +"%s") cp -ral "$RESTORE_DIR" "${LOCAL_WEBSITE_BASE_DIR}/" > $log_file 2>&1 #rsync -a --delete --link-dest="$RESTORE_DIR" "$RESTORE_DIR" "${LOCAL_WEBSITE_BASE_DIR}/" > $log_file 2>&1 retval=$? # End timestamp # e_timestamp=$(date +"%s") duration=$(time_duration $b_timestamp $e_timestamp) echo_duration "$duration" if [[ $retval -eq 0 ]]; then echo_ok else echo_failed #echo -e "\n rsync -a --delete \"$RESTORE_DIR\" \"${LOCAL_WEBSITE_BASE_DIR}/\"" echo -e "\n cp -ral \"$RESTORE_DIR\" \"${LOCAL_WEBSITE_BASE_DIR}/\"" fatal "$(cat $log_file)" fi blank_line if $IS_NEXTCLOUD ; then echononl " Set maintanance mod on site '${WEBSITE}' to 'off'.." if [[ -f "${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}/htdocs/config/config.php" ]] ; then perl -i -n -p -e "s/^(\s*)(.*'maintenance'.*)/\1'maintenance' => false,/" \ "${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}/htdocs/config/config.php" > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed echo -e "\n rsync -a --delete \"$RESTORE_DIR\" \"${LOCAL_WEBSITE_BASE_DIR}/\"" fatal "$(cat $log_file)" fi else echo_skipped error "Configuration file '${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}/htdocs/config/config.php' not found!" fi fi echononl " Set Permissons on local website directory\n '${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}'.." if [[ -d "${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}" ]] ; then chown "$HTTP_USER":"$HTTP_GROUP" "${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}" > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed echo -e "\n chown \"$HTTP_USER\":\"$HTTP_GROUP\" \"${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}\"" error "$(cat $log_file)" fi else echo_skipped fi blank_line echononl " Copy info file 'BACKUP-DATE' to Documentroot.." if [[ -d "${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}" ]]; then echo "${BACKUP_DATE}" > "${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}/BACKUP-DATE" 2> $log_file if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else echo_skipped warn "Local wbesite directory '${LOCAL_WEBSITE_BASE_DIR}/${WEBSITE}' does not exists!" fi # ----- # - Doing some post-script tasks # ----- if $terminal ; then echo "" echo "" echo -e "\033[37m\033[1mDoing some post-script tasks..\033[m" echo "" fi echononl " Set Autocommit to $CUR_AUTOCOMMIT" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL autocommit='$CUR_AUTOCOMMIT'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok CUR_AUTOCOMMIT="" else echo_failed error "$(cat $log_file)" fi echononl " Set foreign_key_checks to $CUR_FOREIGN_KEY_CHECKS" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL foreign_key_checks='$CUR_FOREIGN_KEY_CHECKS'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok CUR_FOREIGN_KEY_CHECKS="" else echo_failed error "$(cat $log_file)" fi echononl " Set unique_checks to $CUR_UNIQUE_CHECKS" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL unique_checks='$CUR_UNIQUE_CHECKS'" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok CUR_UNIQUE_CHECKS="" else echo_failed error "$(cat $log_file)" fi echononl " Set innodb_flush_log_at_trx_commit to $CUR_INNODB_FLUSH_LOG_AT_TRX_COMMIT" mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SET GLOBAL innodb_flush_log_at_trx_commit=$CUR_INNODB_FLUSH_LOG_AT_TRX_COMMIT" >> $log_file 2>&1 if [[ $? -eq 0 ]];then echo_ok CUR_INNODB_FLUSH_LOG_AT_TRX_COMMIT="" else echo_failed error "$(cat $log_file)" fi blank_line echononl " Restart PHP engine.." if [[ "$PHP_ENGINE" = "FPM" ]] && [[ -n "$PHP_VERSION" ]]; then if $SYSTEMD_EXISTS ; then systemctl restart php-${PHP_VERSION}-fpm > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi else /etc/init.d/php-${PHP_VERSION}-fpm restart > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi fi else echo_skipped fi # - Start Apache Webserver # - blank_line echononl " Start Apache Webserver.." if $SYSTEMD_EXISTS ; then systemctl start apache2 > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi else /etc/init.d/apache2 start > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi fi _redis_cli_bin="$(which redis-cli)" if [[ -z "$_redis_cli_bin" ]]; then if [[ -x "/usr/local/bin/redis-cli" ]]; then _redis_cli_bin="/usr/local/bin/redis-cli" fi fi echononl " Flush redis cache.." if [[ -x "$_redis_cli_bin" ]]; then $_redis_cli_bin flushall > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi echononl " Restart redis server.." if $SYSTEMD_EXISTS ; then systemctl restart redis-server > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi else /etc/init.d/redis-server restart > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" fi fi blank_line clean_up 0