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.
#------------------------------------------------------------------------------
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]
-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
}
#------------------------------------------------------------------------------
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
DO_POSTGRES="y"
shift
;;
+ -N|--no-dir-backup)
+ DO_DIR_BACKUP="n"
+ shift
+ ;;
+ --no-sync)
+ DO_SYNC="n"
+ shift
+ ;;
--) shift
break
;;
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}" \
# 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
exit 2
fi
- if [[ -z "${SIMULATE}" ]] ; then
+ if [[ "${SIMULATE}" != 'y' ]] ; then
LOGFILE="${BACKUP_HOSTDIR}/backup.log"
fi
}
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}' ..."
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
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}"
}
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
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
}
#------------------------------------------------------------------------------
-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
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}"
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
}
-#------------------------------------------------------------------------------
-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() {
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
info "Removing '${bdir}' ..."
RM --recursive "${bdir}"
+
done
}
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
#------------------------------------------------------------------------------
main() {
- eval_config
get_options "$@"
umask 0022
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."
}