]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Ubdating bin/manual-backup
authorFrank Brehm <frank@brehm-online.com>
Sun, 12 Jan 2025 11:15:54 +0000 (12:15 +0100)
committerFrank Brehm <frank@brehm-online.com>
Sun, 12 Jan 2025 11:15:54 +0000 (12:15 +0100)
bin/manual-backup

index db45507530e0d1d5b7ae938469c6c5fc2d41e7fc..21c9a7b6bc498c950ff2ba06bafacfb8cdfc610b 100755 (executable)
@@ -28,13 +28,15 @@ REMOVE_DATE=$(date -d "${BACKUP_COPIES} days ago" +"%Y-%m-%d")
 
 LOGFILE=
 BACKUP_DIR="${BACKUP_HOSTDIR}/${CDATE}"
+MYSQL_ERRORLOG=
 
 DO_MYSQL="n"
 DO_POSTGRES="n"
-DO_LDAP="n"
+DO_DIR_BACKUP="y"
+DO_SYNC="y"
 
 declare -a REMOTE_HOSTS=()
-declare -a LDAP_ROOT_DNS=()
+declare -a DATABASES=()
 
 DESCRIPTION=$( cat <<-EOF
        Macht mal eben so ein Backup.
@@ -47,7 +49,7 @@ detect_color
 #------------------------------------------------------------------------------
 usage() {
     cat <<-EOF
-       Usage: ${BASE_NAME} [-C COPIES] [-R REMOTE_HOST [-R REMOTE_HOST ...]] [--mysql] [--pgsql] [Common Options]
+       Usage: ${BASE_NAME} [-C COPIES] [-R REMOTE_HOST [-R REMOTE_HOST ...]] [--mysql] [--pgsql] [-N|--no-dir-backup] [--no-sync] [Common Options]
               ${BASE_NAME} [-h|--help]
               ${BASE_NAME} [-V|--version]
 
@@ -63,6 +65,9 @@ usage() {
                -M|--mysql      Perform a backup of the local MySQL/MariaDB database.
                -P|--pgsql|--postgresql
                                Perform a backup of the local PostrgreSQL database instance.
+               -N|--no-dir-backup
+                               Don't perform directory backups.
+               --no-sync       Don't sync backups to remote host.
        EOF
 
 }
@@ -70,23 +75,11 @@ usage() {
 #------------------------------------------------------------------------------
 TAR() {
 
-    local cmd="tar --create --gzip"
-    if [[ "${VERBOSE}" ]] ; then
-        cmd+=" --verbose"
+    local cmd="tar --create --gzip --file $* >/dev/null 2>&1 || true"
+    if [[ "${VERBOSE}" == "y" ]] ; then
+        cmd="tar --create --gzip --verbose --file $* 2>&1 | tee -a \"${LOGFILE}\" || true"
     fi
-    cmd+=" --file $1"
-    shift
-    while [[ "$#" -gt 0 ]] ; do
-        cmd+=" \"$1\""
-        shift
-    done
-    if [[ "${VERBOSE}" ]] ; then
-        cmd+=" 2>&1 | tee -a \"${LOGFILE}\" || true"
-    else
-        cmd+=" >/dev/null 2>&1 || true"
-    fi
-
-    if [[ "${SIMULATE}" ]] ; then
+    if [[ "${SIMULATE}" == "y" ]] ; then
         info "Executing: ${cmd}"
         return
     fi
@@ -123,6 +116,14 @@ eval_my_options() {
                     DO_POSTGRES="y"
                     shift
                     ;;
+                -N|--no-dir-backup)
+                    DO_DIR_BACKUP="n"
+                    shift
+                    ;;
+                --no-sync)
+                    DO_SYNC="n"
+                    shift
+                    ;;
                 --) shift
                     break
                     ;;
@@ -157,8 +158,8 @@ get_options() {
     local tmp=
     local base_dir=
 
-    local this_short_options='C:R:MP'
-    local this_long_options='copies:,remote:,mysql,pgsql,postgresql'
+    local this_short_options='C:R:MPN'
+    local this_long_options='copies:,remote:,mysql,pgsql,postgresql,no-dir-backup,no-sync'
 
     set +e
     tmp=$( getopt -o "${STD_SHORT_OPTIONS}${this_short_options}" \
@@ -174,7 +175,7 @@ get_options() {
     # Note the quotes around `$TEMP': they are essential!
     eval set -- "${tmp}"
     eval_common_options "$@"
-    if [[ "${DEBUG}" ]] ; then
+    if [[ "${DEBUG}" == 'y' ]] ; then
         declare -p REMAINING_OPTS
         declare -p REMAINING_ARGS
     fi
@@ -195,7 +196,7 @@ get_options() {
         exit 2
     fi
 
-    if [[ -z "${SIMULATE}" ]] ; then
+    if [[ "${SIMULATE}" != 'y' ]] ; then
         LOGFILE="${BACKUP_HOSTDIR}/backup.log"
     fi
 }
@@ -211,6 +212,7 @@ check_preferences() {
     local -a tools=('rsync' 'md5sum' 'sha1sum' 'sha256sum')
     local tool=
     local folder=
+    local i=0
 
     for tool in "${tools[@]}" ; do
         debug "Checking for '${CYAN}${tool}${NORMAL}' ..."
@@ -230,6 +232,15 @@ check_preferences() {
         fi
     done
 
+    debug "Evaluating backup directory ..."
+    BACKUP_DIR="${BACKUP_HOSTDIR}/${CDATE}.${i}"
+    while [[ -e "${BACKUP_DIR}" ]] ; do
+        debug "Path '${CYAN}${BACKUP_DIR}${NORMAL}' is already existing."
+        i=$(( $i + 1 ))
+        BACKUP_DIR="${BACKUP_HOSTDIR}/${CDATE}.${i}"
+    done
+    info "Backup directory is '${CYAN}${BACKUP_DIR}${NORMAL}'."
+
     if [[ "${all_ok}" != "y" ]] ; then
         exit 5
     fi
@@ -241,50 +252,10 @@ dir_backup() {
 
     local bdir="${1}"
     local tarball_base="${2}"
-    local split_dir="n"
-    if [[ "$#" -ge 3 ]] ; then
-        split_dir="$3"
-    fi
-    empty_line
-    debug "Splitting dirs of '${CYAN}/${bdir}${NORMAL}' on dir_backup(): '${CYAN}${split_dir}${NORMAL}'."
-
-    local tarball=
-
-    if [[ "${split_dir}" != "y" ]] ; then
-        tarball="${BACKUP_DIR}/${tarball_base}.tar.gz"
-        info "Backup of '${CYAN}/${bdir}${NORMAL}' => '${CYAN}${tarball}${NORMAL}'."
-        TAR "${tarball}" "${bdir}"
-        return
-    fi
+    local tarball="${BACKUP_DIR}/${tarball_base}.tar.gz"
 
-    local -a non_dirs=()
-    local path=
-    local bname=
-    oifs="${IFS}"
-    IFS="
-"
-
-    for bname in $( ls -1 -A "${bdir}" ) ; do
-        path="${bdir}/${bname}"
-        empty_line
-        debug "Checking path '${CYAN}${path}${NORMAL}' ..."
-        if [[ -d "${path}" ]] ; then
-            tarball="${BACKUP_DIR}/${tarball_base}-${bname}.tar.gz"
-            info "Backup of '${CYAN}${path}${NORMAL}' => '${CYAN}${tarball}${NORMAL}'."
-            TAR "${tarball}" "${path}"
-            continue
-        fi
-        non_dirs+=( "${path}" )
-    done
-
-    IFS="${oifs}"
-
-    if [[ "${#non_dirs[*]}" -ge "1" ]] ; then
-        tarball="${BACKUP_DIR}/${tarball_base}.non_dirs.tar.gz"
-        empty_line
-        info "Backup of non directory paths below '${CYAN}/${bdir}${NORMAL}' => '${CYAN}${tarball}${NORMAL}'."
-        TAR "${tarball}" "${non_dirs[@]}"
-    fi
+    info "Backup of '${CYAN}/${bdir}${NORMAL}' => '${CYAN}${tarball}${NORMAL}'."
+    TAR "${tarball}" "${bdir}"
 
 }
 
@@ -297,18 +268,10 @@ do_dir_backup() {
     empty_line
     info "Starting directory backup ..."
 
-    MKDIR -p "${BACKUP_DIR}"
-
     cd /
     dir_backup "etc" "etc"
     dir_backup "root" "root"
-    if [[ -d "opt/fbrehm" ]] ; then
-        dir_backup "opt/fbrehm" "opt-fbrehm"
-    fi
-    if [[ -d "var/bind" ]] ; then
-        dir_backup "var/bind" "var-bind"
-    fi
-    dir_backup "var/lib" "var-lib" "y"
+    dir_backup "var/lib" "var-lib"
     dir_backup "var/log" "var-log"
     dir_backup "var/spool/cron" "var-spool-cron"
     if [[ -d "var/spool/postfix" ]] ; then
@@ -318,7 +281,7 @@ do_dir_backup() {
         dir_backup "var/vmail" "var-vmail"
     fi
     if [[ -d "var/www" ]] ; then
-        dir_backup "var/www" "var-www" "y"
+        dir_backup "var/www" "var-www"
     fi
 
     for odir in opt/* ; do
@@ -352,42 +315,119 @@ do_dir_backup() {
 }
 
 #------------------------------------------------------------------------------
-do_mysql_backup(){
+eval_mysql_databases() {
 
-    local dumpfile="${BACKUP_DIR}/mysql.dump.all-dbs.dump.sql.gz"
-    local errorlog="${BACKUP_DIR}/mysql.dump.error.log"
+    local dbname=
+    local oifs="${IFS}"
+    IFS="
+"   
+    local db=
+    local db_uc=
+    local do_ignore=
 
     empty_line
-    info "Dumping MySQL Datenbank -> '${CYAN}${dumpfile}${NORMAL}' ..."
+    info "Evaluating all databases for backup."
+
+    for dbname in $( mysql -s -r -N -e 'SHOW DATABASES' ) ; do
+
+        if [[ "${dbname}" == 'performance_schema' ]] ; then
+            continue
+        elif [[ "${dbname}" == 'information_schema' ]] ; then
+            continue
+        fi
+
+        db_uc=$( echo "${dbname}" | tr '[:upper:]' '[:lower:]' )
+        do_ignore="n"
+        for db in "${!ALL_DATABASES_IGNORE[@]}" ; do
+            if [[ "${db}" == "${db_uc}" ]] ; then
+                do_ignore="y"
+                break
+            fi
+        done
+        if [[ "${do_ignore}" == "y" ]] ; then
+            debug "Ignoring database '${CYAN}${dbname}${NORMAL}'."
+            continue
+        fi
+
+        debug "Adding database '${CYAN}${dbname}${NORMAL}'."
+        DATABASES+=( "${dbname}" )
+
+    done
+    if [[ "${DEBUG}" == 'y' ]] ; then
+        declare -p DATABASES
+    fi
 
-    local cmd="mysqldump --all_databases --routines --triggers --add-drop-database"
-    cmd+=" --add-drop-table --complete-insert --extended-insert --lock-tables"
-    if [[ "${VERBOSE}" ]] ; then
+    IFS="${oifs}"
+
+    if [[ "${VERBOSE}" == "y" ]] ; then
+        echo
+        echo "Following databases will be backed up:"
+        for dbname in "${DATABASES[@]}" ; do
+           echo "  * '${dbname}'"
+        done
+    fi
+
+
+}
+
+#------------------------------------------------------------------------------
+backup_mysql_database() {
+
+    local db="${1}"
+    local dumpfile="${BACKUP_DIR}/mysql.dump.${db}.sql.gz"
+
+    empty_line
+    info "Backup of database '${CYAN}${db}${NORMAL}' into file '${dumpfile}' ..."
+
+    local db_uc=$( echo "${db}" | tr '[:upper:]' '[:lower:]' )
+
+    local cmd="mysqldump --routines --triggers --add-drop-database --add-drop-table"
+    cmd+=" --complete-insert --extended-insert --lock-tables"
+    cmd+=" --opt --flush-logs --single-transaction"
+    cmd+=" --databases \"${db}\" "
+    if [[ "${VERBOSE}" == "y" ]] ; then
         cmd+=" --verbose"
     fi
-    cmd+=" --log-error=\"${errorlog}\""
+    cmd+=" --log-error=\"${MYSQL_ERRORLOG}\""
     cmd+=" | gzip -9"
-    if [[ "${VERBOSE}" ]] ; then
+    if [[ "${VERBOSE}" == "y" ]] ; then
         cmd+=" --verbose"
     fi
     cmd+=" > \"${dumpfile}\""
-    if [[ "${SIMULATE}" ]] ; then
+
+    if [[ "${SIMULATE}" == "y" ]] ; then
         info "Executing: ${cmd}"
-        return
+    else
+        debug "Executing: ${cmd}"
+        eval ${cmd}
     fi
-    debug "Executing: ${cmd}"
-    eval ${cmd}
-    if [[ -e "${errorlog}" ]] ; then
-        if [[ -s "${errorlog}" ]] ; then
-            cmd="gzip -9 \"${errorlog}\""
-            if [[ "${VERBOSE}" ]] ; then
-                cmd="gzip -9 --verbose \"${errorlog}\""
+
+}
+
+#------------------------------------------------------------------------------
+do_mysql_backup(){
+
+    local dbname=
+
+    MYSQL_ERRORLOG="${BACKUP_DIR}/mysql.dump.error.log"
+
+    eval_mysql_databases
+
+    for dbname in "${DATABASES[@]}" ; do
+        backup_mysql_database "${dbname}"
+    done
+
+    if [[ -e "${MYSQL_ERRORLOG}" ]] ; then
+        if [[ -s "${MYSQL_ERRORLOG}" ]] ; then
+            cmd="gzip -9 \"${MYSQL_ERRORLOG}\""
+            if [[ "${VERBOSE}" == "y" ]] ; then
+                cmd="gzip -9 --verbose \"${MYSQL_ERRORLOG}\""
             fi
             info "Executing: ${cmd}"
             eval ${cmd}
         else
-            debug "Removing empty '${CYAN}${errorlog}${NORMAL}' ..."
-            RM "${errorlog}"
+            debug "Removing empty '${CYAN}${MYSQL_ERRORLOG}${NORMAL}' ..."
+            RM "${MYSQL_ERRORLOG}"
         fi
     fi
 
@@ -402,16 +442,16 @@ do_postgres_backup() {
     debug "Dumping PostgreSQL globals ..."
     local dumpfile="${BACKUP_DIR}/postgres.@globals.dump.sql.gz"
     local cmd="su - postgres -c \"pg_dumpall"
-    if [[ "${VERBOSE}" ]] ; then
+    if [[ "${VERBOSE}" == "y" ]] ; then
         cmd+=" --verbose"
     fi
     cmd+=" --globals-only --clean --encoding=utf-8 --disable-triggers --if-exists\""
     cmd+=" | gzip -9"
-    if [[ "${VERBOSE}" ]] ; then
+    if [[ "${VERBOSE}" == "y" ]] ; then
         cmd+=" --verbose"
     fi
     cmd+=" > \"${dumpfile}\""
-    if [[ "${SIMULATE}" ]] ; then
+    if [[ "${SIMULATE}" == "y" ]] ; then
         info "Executing: ${cmd}"
     else
         debug "Executing: ${cmd}"
@@ -429,16 +469,16 @@ do_postgres_backup() {
         debug "Dumping PostgreSQL database '${CYAN}${db}${NORMAL}' ..."
         dumpfile="${BACKUP_DIR}/postgres.${db}.dump.sql.gz"
         cmd="su - postgres -c \"pg_dump"
-        if [[ "${VERBOSE}" ]] ; then
+        if [[ "${VERBOSE}" == "y" ]] ; then
             cmd+=" --verbose"
         fi
         cmd+=" --blobs --clean --create --encoding=utf-8 --disable-triggers --if-exists '${db}'\""
         cmd+=" | gzip -9"
-        if [[ "${VERBOSE}" ]] ; then
+        if [[ "${VERBOSE}" == "y" ]] ; then
             cmd+=" --verbose"
         fi
         cmd+=" > \"${dumpfile}\""
-        if [[ "${SIMULATE}" ]] ; then
+        if [[ "${SIMULATE}" == "y" ]] ; then
             info "Executing: ${cmd}"
             continue
         fi
@@ -448,71 +488,6 @@ do_postgres_backup() {
 
 }
 
-#------------------------------------------------------------------------------
-do_backup_ldap() {
-
-
-    if ps -ef | grep slapd | grep -v grep >/dev/null ; then
-        :
-    else
-        debug "OpenLDAP Server is not running."
-        return
-    fi
-
-    local dumpfile="${BACKUP_DIR}/ldap-cfg.dump.ldif.gz"
-
-    empty_line
-    info "Dumping OpenLDAP Config -> '${CYAN}${dumpfile}${NORMAL}' ..."
-    local cmd="ldapsearch -Y EXTERNAL -Q -LLL -o ldif-wrap=no -H ldapi:/// -b \"cn=config\""
-    if [[ "${VERBOSE}" ]] ; then
-        cmd+=" -v"
-    fi
-    cmd+=" | gzip -9"
-    if [[ "${VERBOSE}" ]] ; then
-        cmd+=" --verbose"
-    fi
-    cmd+=" > \"${dumpfile}\""
-    if [[ "${SIMULATE}" ]] ; then
-        info "Executing: ${cmd}"
-    else
-        debug "Executing: ${cmd}"
-        eval ${cmd}
-    fi
-
-    local dn=
-    local clean_dn=
-
-    for dn in "${LDAP_ROOT_DNS[@]}" ; do
-
-        clean_dn=$( echo "${dn}" | sed -e 's/^[        ]*//' -e 's/[   ]*$//' -e 's/[  ][      ]*/_/g' )
-        dumpfile="${BACKUP_DIR}/ldap-db.${clean_dn}.dump.ldif.gz"
-
-        empty_line
-        info "Dumping OpenLDAP Datenbank '${CYAN}${dn}${NORMAL}' -> '${CYAN}${dumpfile}${NORMAL}' ..."
-
-        cmd="ldapsearch -Y EXTERNAL -Q -LLL -o ldif-wrap=no -H ldapi:///"
-        if [[ "${VERBOSE}" ]] ; then
-            cmd+=" -v"
-        fi
-        cmd+=" -b \"${dn}\" '+' '*' | gzip -9"
-        if [[ "${VERBOSE}" ]] ; then
-            cmd+=" --verbose"
-        fi
-        cmd+=" > \"${dumpfile}\""
-        if [[ "${SIMULATE}" ]] ; then
-            info "Executing: ${cmd}"
-        else
-            debug "Executing: ${cmd}"
-            eval ${cmd}
-        fi
-
-    done
-
-    debug "Finished LDAP dump."
-
-}
-
-
 #------------------------------------------------------------------------------
 create_checksums() {
 
@@ -531,7 +506,7 @@ create_checksums() {
         cs_file="backup-checksums.${cs_type}"
         info "Creating '${CYAN}${cs_file}${NORMAL}' ..."
         cmd="${cs_type}sum *.gz > \"${cs_file}\""
-        if [[ "${SIMULATE}" ]] ; then
+        if [[ "${SIMULATE}" == "y" ]] ; then
             info "Executing: ${cmd}"
             continue
         fi
@@ -583,6 +558,7 @@ clean_old_backups() {
         info "Removing '${bdir}' ..."
         RM --recursive "${bdir}"
 
+
     done
 
 }
@@ -598,16 +574,16 @@ sync_to_remote() {
         empty_line
         info "Syncing backup to '${GREEN}${rhost}${NORMAL}:${CYAN}${BACKUP_HOSTDIR}${NORMAL}' ..."
         cmd="rsync --archive --hard-links --delete --stats"
-        if [[ "${VERBOSE}" ]] ; then
+        if [[ "${VERBOSE}" == "y" ]] ; then
             cmd+=" --verbose"
         fi
         cmd+=" \"${BACKUP_HOSTDIR}\" \"${rhost}:${BACKUP_PARENTDIR}\""
-        if [[ "${QUIET}" ]] ; then
+        if [[ "${QUIET}" == "y" ]] ; then
             cmd+=" >> \"${LOGFILE}\" 2>&1"
         else
             cmd+=" 2>&1 | tee -a \"${LOGFILE}\""
         fi
-        if [[ "${SIMULATE}" ]] ; then
+        if [[ "${SIMULATE}" == "y" ]] ; then
             info "Executing: ${cmd}"
             continue
         fi
@@ -621,7 +597,6 @@ sync_to_remote() {
 #------------------------------------------------------------------------------
 main() {
 
-    eval_config
     get_options "$@"
     umask 0022
 
@@ -631,19 +606,28 @@ main() {
     empty_line
 
     check_preferences
-    do_dir_backup
+    MKDIR -p "${BACKUP_DIR}"
+
+    if [[ "${DO_DIR_BACKUP}" == 'y' ]] ; then
+        do_dir_backup
+    else
+        empty_line
+        warn "Don't execute directory backups."
+    fi
     if [[ "${DO_MYSQL}" == "y" ]] ; then
         do_mysql_backup
     fi
     if [[ "${DO_POSTGRES}" == "y" ]] ; then
         do_postgres_backup
     fi
-    if [[ "${DO_LDAP}" == "y" ]] ; then
-        do_backup_ldap
-    fi
     create_checksums
     clean_old_backups
-    sync_to_remote
+    if [[ "${DO_SYNC}" == "y" ]] ; then
+        sync_to_remote
+    else
+        empty_line
+        warn "Don't execute the sync to the remote hosts."
+    fi
 
     info "Finished."
 }