From 89f44eec6d970a617272dc812183903f475979f4 Mon Sep 17 00:00:00 2001 From: Martin Gruner Date: Mon, 21 Jun 2021 10:11:10 +0000 Subject: [PATCH] Maintenance: Improve backup and restore handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Made parsing of database configuration more robust. * Improved PostgreSQL handling for better password handling and to support remote databases. * Other small fixes. * Closes #3352, closes #3561, closes: #3621. Special thanks to Alexander (7adietri) and Michal Čihař (nijel) for their PRs on this. --- contrib/backup/functions | 47 ++++++++++++++++++++++++-------- contrib/backup/zammad_backup.sh | 1 - contrib/backup/zammad_restore.sh | 1 - 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/contrib/backup/functions b/contrib/backup/functions index 205be5706..05d25bbad 100644 --- a/contrib/backup/functions +++ b/contrib/backup/functions @@ -23,13 +23,15 @@ function delete_old_backups () { } function get_db_credentials () { - DB_ADAPTER="$(grep 'adapter:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*adapter:\(\| \)//g')" - DB_NAME="$(grep 'database:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*database:\(\| \) //g')" - DB_USER="$(grep 'username:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*username:\(\| \)//g')" - DB_PASS="$(grep 'password:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*password:\(\| \)//g')" + DB_ADAPTER="$(grep -m 1 '^[[:space:]]*adapter:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*adapter:[[:space:]]*//g')" + DB_HOST="$(grep -m 1 '^[[:space:]]*host:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*host:[[:space:]]*//g')" + DB_PORT="$(grep -m 1 '^[[:space:]]*port:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*port:[[:space:]]*//g')" + DB_NAME="$(grep -m 1 '^[[:space:]]*database:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*database:[[:space:]]* //g')" + DB_USER="$(grep -m 1 '^[[:space:]]*username:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*username:[[:space:]]*//g')" + DB_PASS="$(grep -m 1 '^[[:space:]]*password:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*password:[[:space:]]*//g')" if [ "${DEBUG}" == "yes" ]; then - echo "adapter=${DB_ADAPTER} dbname=${DB_NAME} dbuser=${DB_USER} dbpass=${DB_PASS}" + echo "adapter=${DB_ADAPTER} dbhost=${DB_HOST} dbport=${DB_PORT} dbname=${DB_NAME} dbuser=${DB_USER} dbpass=${DB_PASS}" fi } @@ -47,6 +49,15 @@ function backup_files () { ln -sfn ${BACKUP_DIR}/${TIMESTAMP}_zammad_files.tar.gz ${BACKUP_DIR}/latest_zammad_files.tar.gz } +function create_pgpassfile() { + export PGPASSFILE=$(mktemp) + chmod 600 "$PGPASSFILE" + cat < "$PGPASSFILE" +*:*:${DB_NAME}:${DB_USER}:${DB_PASS} +EOT + trap 'rm "$PGPASSFILE"' EXIT +} + function backup_db () { if [ "${DB_ADAPTER}" == "mysql2" ]; then echo "creating mysql backup..." @@ -54,9 +65,16 @@ function backup_db () { ln -sfn ${BACKUP_DIR}/${TIMESTAMP}_zammad_db.mysql.gz ${BACKUP_DIR}/latest_zammad_db.mysql.gz elif [ "${DB_ADAPTER}" == "postgresql" ]; then echo "creating postgresql backup..." - su -c "pg_dump --no-privileges --no-owner -c ${DB_NAME} | \ - gzip > /tmp/${TIMESTAMP}_zammad_db.psql.gz" postgres - mv /tmp/${TIMESTAMP}_zammad_db.psql.gz ${BACKUP_DIR} + + create_pgpassfile + + pg_dump --dbname "${DB_NAME}" \ + --username "${DB_USER}" \ + ${DB_HOST:+--host $DB_HOST} \ + ${DB_PORT:+--port $DB_PORT} \ + --no-privileges --no-owner \ + --compress 6 --file "${BACKUP_DIR}/${TIMESTAMP}_zammad_db.psql.gz" + ln -sfn ${BACKUP_DIR}/${TIMESTAMP}_zammad_db.psql.gz ${BACKUP_DIR}/latest_zammad_db.psql.gz else echo "DB ADAPTER not found. if its sqlite backup is already saved in the filebackup" @@ -180,7 +198,7 @@ function restore_zammad () { zammad run rake db:drop zammad config:set DISABLE_DATABASE_ENVIRONMENT_CHECK=0 else - ${ZAMMAD_DIR}/bin/rake db:drop + DISABLE_DATABASE_ENVIRONMENT_CHECK=1 ${ZAMMAD_DIR}/bin/rake db:drop fi echo "# ... Creating database ${DB_NAME} for owner ${DB_USER}" @@ -191,11 +209,16 @@ function restore_zammad () { ${ZAMMAD_DIR}/bin/rake db:create fi - echo "# Restoring PostgrSQL DB" - zcat ${BACKUP_DIR}/${RESTORE_DB_DATE}_zammad_db.${DB_FILE_EXT}.gz | su -c "psql -d ${DB_NAME}" zammad + echo "# Restoring PostgreSQL DB" + + create_pgpassfile + + zcat < ${BACKUP_DIR}/${RESTORE_DB_DATE}_zammad_db.${DB_FILE_EXT}.gz \ + | psql ${DB_HOST:+--host $DB_HOST} ${DB_PORT:+--port $DB_PORT} ${DB_USER:+--username $DB_USER} --dbname ${DB_NAME} + elif [ "${DB_ADAPTER}" == "mysql2" ]; then echo "# Restoring MySQL DB" - zcat ${BACKUP_DIR}/${RESTORE_DB_DATE}_zammad_db.${DB_FILE_EXT}.gz | mysql -u${DB_USER} -p${DB_PASS} ${DB_NAME} + zcat < ${BACKUP_DIR}/${RESTORE_DB_DATE}_zammad_db.${DB_FILE_EXT}.gz | mysql -u${DB_USER} -p${DB_PASS} ${DB_NAME} fi if command -v zammad > /dev/null; then diff --git a/contrib/backup/zammad_backup.sh b/contrib/backup/zammad_backup.sh index b7f6d3259..dd2ce68b1 100755 --- a/contrib/backup/zammad_backup.sh +++ b/contrib/backup/zammad_backup.sh @@ -3,7 +3,6 @@ # zammad backup script # -PATH=/sbin:/bin:/usr/sbin:/usr/bin: # shellcheck disable=SC2046 BACKUP_SCRIPT_PATH="$(dirname $(realpath $0))" diff --git a/contrib/backup/zammad_restore.sh b/contrib/backup/zammad_restore.sh index 0166240e4..5a327fa43 100755 --- a/contrib/backup/zammad_restore.sh +++ b/contrib/backup/zammad_restore.sh @@ -3,7 +3,6 @@ # zammad restore script # -PATH=/sbin:/bin:/usr/sbin:/usr/bin: # shellcheck disable=SC2046 BACKUP_SCRIPT_PATH="$(dirname $(realpath $0))"