diff --git a/borg2-backup-nc.sh b/borg2-backup-nc.sh index c34fb5c..94af9c6 100755 --- a/borg2-backup-nc.sh +++ b/borg2-backup-nc.sh @@ -23,6 +23,7 @@ clean_up() { # Perform program exit housekeeping sudo -u ${HTTP_USER} ${PHP_COMMAND} ${NC_PATH}/occ maintenance:mode --off > /dev/null 2>&1 + rm -f ${NC_DB_BACKUP_DIR}/*-${backup_date}.sql rm -rf "$LOCK_DIR" blank_line exit $1 @@ -140,6 +141,14 @@ echo_wait(){ fi } +## - 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 @@ -214,6 +223,10 @@ DEFAULT_MYSQL_CREDENTIALS="-u root -S /run/mysqld/mysqld.sock" DEFAULT_MYSQL_PERFORMANCE_SETTINGS=false DEFAULT_MYSQL_MAX_ALLOWED_PACKET="512M" +DEFAULT_DB_TYPE="None" + +DEFAULT_PSQL_SYSTEM_USER="postgres" + DEFAULT_BACKUP_OTHER_DIRECTORIES="/etc /home /root /var/spool/cron" DEFAULT_KEEP_DAILY=10 @@ -245,6 +258,27 @@ fi [[ -z "${MYSQL_PERFORMANCE_SETTINGS}" ]] && MYSQL_PERFORMANCE_SETTINGS=${DEFAULT_MYSQL_PERFORMANCE_SETTINGS} [[ -z "$MYSQL_MAX_ALLOWED_PACKET" ]] && MYSQL_MAX_ALLOWED_PACKET="${DEFAULT_MYSQL_MAX_ALLOWED_PACKET}" +if [[ -z "${DB_TYPE}" ]] ; then + DB_TYPE="${DEFAULT_DB_TYPE}" +else + # replace comma by blank sign + DB_TYPE=${DB_TYPE/,/ } +fi + +declare -a db_type_arr=() + +for _db_type in ${DB_TYPE}; do + if [[ "${_db_type,,}" = "psql" ]] || [[ "${_db_type,,}" = "postgresql" ]] || [[ "${_db_type,,}" = "postgres" ]] ; then + db_type_arr+=("postgresql") + else + db_type_arr+=("${_db_type,,}") + fi +done + +if containsElement "postgresql" "${db_type_arr[@]}" ; then + [[ -z "${PSQL_SYSTEM_USER}" ]] && PSQL_SYSTEM_USER="${DEFAULT_PSQL_SYSTEM_USER}" +fi + # ------------- # - Job is already running? # ------------- @@ -444,6 +478,8 @@ echo "FROM_ADDRESS=\"${FROM_ADDRESS}\"" >> ${BORG_LOG_FILE} echo "" >> ${BORG_LOG_FILE} echo "PHP_COMMAND=\"${PHP_COMMAND}\"" >> ${BORG_LOG_FILE} echo "" >> ${BORG_LOG_FILE} +echo "DB_TYPE=\"${DB_TYPE}\"" >> ${BORG_LOG_FILE} +echo "" >> ${BORG_LOG_FILE} @@ -757,6 +793,164 @@ if ${MYSQL_PERFORMANCE_SETTINGS}; then fi +if containsElement "mysql" "${db_type_arr[@]}" ; then + + if $terminal ; then + echo "" + echo -e " \033[1m---\033[m" + echo -e " \033[32mCreate additional MySQL database backup(s).. \033[m" + echo -e " \033[1m---\033[m" + fi + + blank_line + + echononl "Create an array of additional MySQL databases." + + cat <> ${BORG_LOG_FILE} +declare -a mysql_database_arr=(); +for _db_name in \$(mysql ${MYSQL_CREDENTIALS} -s -r -N -e 'show databases' 2> /dev/null ) ; do + + [[ "\${_db_name}" = "information_schema" ]] && continue + [[ "\${_db_name}" = "performance_schema" ]] && continue + [[ "\${_db_name}" = "mysql" ]] && continue + [[ "\${_db_name}" = "sys" ]] && continue + [[ "\${_db_name}" = "${NC_DB}" ]] && continue + + mysql_database_arr+=("\${_db_name}") + +done +EOF + + declare -a mysql_database_arr=(); + for _db_name in $(mysql ${MYSQL_CREDENTIALS} -s -r -N -e 'show databases' 2> ${log_file}) ; do + + [[ "${_db_name}" = "information_schema" ]] && continue + [[ "${_db_name}" = "performance_schema" ]] && continue + [[ "${_db_name}" = "mysql" ]] && continue + [[ "${_db_name}" = "sys" ]] && continue + [[ "${_db_name}" = "${NC_DB}" ]] && continue + + mysql_database_arr+=("${_db_name}") + + done + + if [[ -s "${log_file}" ]] ; then + echo_failed + error "$(cat "${log_file}")" + else + echo_ok + fi + + blank_line + + for _db in "${mysql_database_arr[@]}" ; do + + echononl " Dump MySQL Database '${_db}'.." + + cat <> ${BORG_LOG_FILE} +mysqldump ${MYSQL_CREDENTIALS} \\ + --single-transaction \\ + --max-allowed-packet=${MYSQL_MAX_ALLOWED_PACKET} \\ + --routines \\ + --triggers \\ + --quick \\ + --extended-insert ${_db} > ${NC_DB_BACKUP_DIR}/${_db}-mysql-${backup_date}.sql + +EOF + + mysqldump $MYSQL_CREDENTIALS \ + --single-transaction \ + --max-allowed-packet=${MYSQL_MAX_ALLOWED_PACKET} \ + --routines \ + --triggers \ + --quick \ + --extended-insert ${_db} > ${NC_DB_BACKUP_DIR}/${_db}-mysql-${backup_date}.sql 2> ${log_file} + + if [[ -s "${log_file}" ]] ; then + echo_failed + error "$(cat "${log_file}")" + else + echo_ok + fi + + done + + blank_line + +fi + +if containsElement "postgresql" "${db_type_arr[@]}" ; then + + if $terminal ; then + echo "" + echo -e " \033[1m---\033[m" + echo -e " \033[32mCreate PostgreSQL database backup(s).. \033[m" + echo -e " \033[1m---\033[m" + fi + + blank_line + + echononl "Create an array of PostgreSQL databases." + + cat <> ${BORG_LOG_FILE} +declare -a psql_database_arr=(); +for _db_name in \$(su - ${PSQL_SYSTEM_USER} -c "psql -lt" 2> /dev/null | grep -v -e"^$" | awk '{print\$1}') ; do + + [[ "\${_db_name}" = "template0" ]] && continue + [[ "\${_db_name}" = "template1" ]] && continue + [[ "\${_db_name}" = "postgres" ]] && continue + [[ "\${_db_name}" = "|" ]] && continue + [[ "\${_db_name}" = ":" ]] && continue + + psql_database_arr+=("\${_db_name}") + +done +EOF + + declare -a psql_database_arr=(); + for _db_name in $(su - ${PSQL_SYSTEM_USER} -c "psql -lt" 2> "${log_file}" | grep -v -e"^$" | awk '{print$1}') ; do + + [[ "${_db_name}" = "template0" ]] && continue + [[ "${_db_name}" = "template1" ]] && continue + [[ "${_db_name}" = "postgres" ]] && continue + [[ "${_db_name}" = "|" ]] && continue + [[ "${_db_name}" = ":" ]] && continue + + psql_database_arr+=("${_db_name}") + + done + + if [[ -s "${log_file}" ]] ; then + echo_failed + error "$(cat "${log_file}")" + else + echo_ok + fi + + for _db in "${psql_database_arr[@]}" ; do + + echononl " Dump PostgreSQL Database '${_db}'.." + + cat <> ${BORG_LOG_FILE} +su - ${PSQL_SYSTEM_USER} -c "pg_dump -c ${_db}" > ${NC_DB_BACKUP_DIR}/${_db}-psql-${backup_date}.sql +EOF + + su - ${PSQL_SYSTEM_USER} -c "pg_dump -c ${_db}" > ${NC_DB_BACKUP_DIR}/${_db}-psql-${backup_date}.sql 2> ${log_file} + + if [[ -s "${log_file}" ]] ; then + echo_failed + error "$(cat "${log_file}")" + else + echo_ok + fi + + done + + blank_line + +fi + + echononl "Create borg backup.." cat << EOF >> ${BORG_LOG_FILE} @@ -912,9 +1106,9 @@ fi # echononl "Remove local DB backup.." -echo "rm ${NC_DB_BACKUP_DIR}/${NC_DB}-${backup_date}.sql" >> ${BORG_LOG_FILE} +echo "rm -f ${NC_DB_BACKUP_DIR}/*-${backup_date}.sql" >> ${BORG_LOG_FILE} -rm ${NC_DB_BACKUP_DIR}/${NC_DB}-${backup_date}.sql > ${log_file} 2>&1 +rm -f ${NC_DB_BACKUP_DIR}/*-${backup_date}.sql > ${log_file} 2>&1 if [[ $? -gt 0 ]] ; then echo_failed diff --git a/conf/borg2-backup-nc.conf.sample b/conf/borg2-backup-nc.conf.sample index 7570c73..80d1d94 100644 --- a/conf/borg2-backup-nc.conf.sample +++ b/conf/borg2-backup-nc.conf.sample @@ -118,6 +118,60 @@ # DB related parameters # --- +# DB_TYPE +# +# Which additional database(s) should be backed up (in addition to the Nextcloud DB)? +# +# The Nextcloud database is always backed up automatically via 'occ'. +# Use this parameter to also back up other (non-Nextcloud) databases on this host. +# +# Possible values: +# - MySQL (or mysql) +# - PostgreSQL (or postgres or psql) +# - MySQL,PostgreSQL (or MySQL PostgreSQL - comma or space separated) +# - None +# +# When set to MySQL: all MySQL databases except the Nextcloud DB and system +# databases (information_schema, performance_schema, mysql, sys) are backed up. +# +# Defaults to: +# +# DB_TYPE="None" +# +#DB_TYPE="None" + + +# MYSQL_CREDENTIALS +# +# Giving password on command line is insecure and since mysql 5.5 +# you will get a warning doing so. +# +# Reading username/password from file is also possible, using MySQL/MariaDB +# commandline parameter '--defaults-file'. +# +# Since Version 5.6, that method is considered as insecure. +# To avoid giving the password on command line, we use an +# encrypted option file. +# +# Create (encrypted) option file: +# $ mysql_config_editor set --login-path=local --socket=/var/run/mysqld/mysqld.sock --user=backup --password +# $ Password: +# +# Use of option file: +# $ mysql --login-path=local ... +# +# Example +# MYSQL_CREDENTIALS="--login-path=local" +# MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf" (Debian default) +# MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf" +# +# Defaults to: +# +# MYSQL_CREDENTIALS="-u root -S /run/mysqld/mysqld.sock" +# +#MYSQL_CREDENTIALS="-u root -S /run/mysqld/mysqld.sock" + + # MYSQL_PERFORMANCE_SETTINGS # # To increase performance, some global variables are changed before writing the database dump. @@ -140,13 +194,24 @@ # MYSQL_MAX_ALLOWED_PACKET # -# Set/Change this value only for dumping the NC database +# Maximum packet size for mysqldump (applies to NC DB and additional MySQL databases) # # Defaults to: # -# #MYSQL_MAX_ALLOWED_PACKET=1G +# MYSQL_MAX_ALLOWED_PACKET="512M" # -#MYSQL_MAX_ALLOWED_PACKET=1G +#MYSQL_MAX_ALLOWED_PACKET="512M" + + +# PSQL_SYSTEM_USER +# +# User who owns PostgreSQL services +# +# Defaults to: +# +# PSQL_SYSTEM_USER="postgres" +# +#PSQL_SYSTEM_USER="postgres" # ---