Maintenance: Improve backup and restore handling.

* 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.
This commit is contained in:
Martin Gruner 2021-06-21 10:11:10 +00:00
parent 2cab5742b2
commit 89f44eec6d
3 changed files with 35 additions and 14 deletions

View file

@ -23,13 +23,15 @@ function delete_old_backups () {
} }
function get_db_credentials () { function get_db_credentials () {
DB_ADAPTER="$(grep 'adapter:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*adapter:\(\| \)//g')" DB_ADAPTER="$(grep -m 1 '^[[:space:]]*adapter:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*adapter:[[:space:]]*//g')"
DB_NAME="$(grep 'database:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*database:\(\| \) //g')" DB_HOST="$(grep -m 1 '^[[:space:]]*host:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*host:[[:space:]]*//g')"
DB_USER="$(grep 'username:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*username:\(\| \)//g')" DB_PORT="$(grep -m 1 '^[[:space:]]*port:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*port:[[:space:]]*//g')"
DB_PASS="$(grep 'password:' < ${ZAMMAD_DIR}/config/database.yml | sed -e 's/.*password:\(\| \)//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 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 fi
} }
@ -47,6 +49,15 @@ function backup_files () {
ln -sfn ${BACKUP_DIR}/${TIMESTAMP}_zammad_files.tar.gz ${BACKUP_DIR}/latest_zammad_files.tar.gz 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 <<EOT > "$PGPASSFILE"
*:*:${DB_NAME}:${DB_USER}:${DB_PASS}
EOT
trap 'rm "$PGPASSFILE"' EXIT
}
function backup_db () { function backup_db () {
if [ "${DB_ADAPTER}" == "mysql2" ]; then if [ "${DB_ADAPTER}" == "mysql2" ]; then
echo "creating mysql backup..." 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 ln -sfn ${BACKUP_DIR}/${TIMESTAMP}_zammad_db.mysql.gz ${BACKUP_DIR}/latest_zammad_db.mysql.gz
elif [ "${DB_ADAPTER}" == "postgresql" ]; then elif [ "${DB_ADAPTER}" == "postgresql" ]; then
echo "creating postgresql backup..." echo "creating postgresql backup..."
su -c "pg_dump --no-privileges --no-owner -c ${DB_NAME} | \
gzip > /tmp/${TIMESTAMP}_zammad_db.psql.gz" postgres create_pgpassfile
mv /tmp/${TIMESTAMP}_zammad_db.psql.gz ${BACKUP_DIR}
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 ln -sfn ${BACKUP_DIR}/${TIMESTAMP}_zammad_db.psql.gz ${BACKUP_DIR}/latest_zammad_db.psql.gz
else else
echo "DB ADAPTER not found. if its sqlite backup is already saved in the filebackup" 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 run rake db:drop
zammad config:set DISABLE_DATABASE_ENVIRONMENT_CHECK=0 zammad config:set DISABLE_DATABASE_ENVIRONMENT_CHECK=0
else else
${ZAMMAD_DIR}/bin/rake db:drop DISABLE_DATABASE_ENVIRONMENT_CHECK=1 ${ZAMMAD_DIR}/bin/rake db:drop
fi fi
echo "# ... Creating database ${DB_NAME} for owner ${DB_USER}" echo "# ... Creating database ${DB_NAME} for owner ${DB_USER}"
@ -191,11 +209,16 @@ function restore_zammad () {
${ZAMMAD_DIR}/bin/rake db:create ${ZAMMAD_DIR}/bin/rake db:create
fi fi
echo "# Restoring PostgrSQL DB" echo "# Restoring PostgreSQL DB"
zcat ${BACKUP_DIR}/${RESTORE_DB_DATE}_zammad_db.${DB_FILE_EXT}.gz | su -c "psql -d ${DB_NAME}" zammad
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 elif [ "${DB_ADAPTER}" == "mysql2" ]; then
echo "# Restoring MySQL DB" 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 fi
if command -v zammad > /dev/null; then if command -v zammad > /dev/null; then

View file

@ -3,7 +3,6 @@
# zammad backup script # zammad backup script
# #
PATH=/sbin:/bin:/usr/sbin:/usr/bin:
# shellcheck disable=SC2046 # shellcheck disable=SC2046
BACKUP_SCRIPT_PATH="$(dirname $(realpath $0))" BACKUP_SCRIPT_PATH="$(dirname $(realpath $0))"

View file

@ -3,7 +3,6 @@
# zammad restore script # zammad restore script
# #
PATH=/sbin:/bin:/usr/sbin:/usr/bin:
# shellcheck disable=SC2046 # shellcheck disable=SC2046
BACKUP_SCRIPT_PATH="$(dirname $(realpath $0))" BACKUP_SCRIPT_PATH="$(dirname $(realpath $0))"