#!/bin/bash # ================================================================================ # # LOCALDUMP :: POSTGRES # create gzipped plain text backups from each scheme # # -------------------------------------------------------------------------------- # ah - Axel Hahn <axel.hahn@iml.unibe.ch> # ds - Daniel Schueler <daniel.schueler@iml.unibe.ch> # # 2016-11-10 ah,ds v1.0 # 2017-03-29 ..... v1.1 added restore # 2022-01-20 v1.2 fixes with shellcheck # 2022-03-17 v1.3 WIP: add lines with prefix __DB__ # 2023-09-20 v1.4 FIX could not change directory to "/root": Permission denied # 2024-10-02 ah v1.5 rename backup and restore function # 2024-12-13 ah v1.6 backup uses a snapshot db # 2024-12-16 ah v1.7 on snapshot mode it can fallback for single database to normal pg_dump of origin # ================================================================================ if [ -z "$BACKUP_TARGETDIR" ]; then echo "ERROR: you cannot start $(basename $0) directly" rc=$rc+1 exit 1 fi # -------------------------------------------------------------------------------- # CONFIG # -------------------------------------------------------------------------------- # unix user of postgres database PGUSER=postgres # -------------------------------------------------------------------------------- # FUNCTION # -------------------------------------------------------------------------------- # backup all databases function pgsql.backup(){ local DATABASE local SNAPSHOTDB local OUTFILE local snapshotprefix="snapshot_" local bUseSnapshot local bUseSnapshot4DB typeset -i bUseSnapshot=0 create_targetdir # ----- change owner of directory because of su command chown ${PGUSER}. "${BACKUP_TARGETDIR}" # ----- GO # prevent could not change directory to "/root": Permission denied ( cd /tmp # Detect a readonly or writeable postgres host. TESTDB="imlbackup_createtest" su ${PGUSER} -c "dropdb ${TESTDB}" >/dev/null 2>&1 if su ${PGUSER} -c "psql ${BACKUP_PARAMS} -c \"CREATE DATABASE ${TESTDB};\"" >/dev/null 2>&1 then bUseSnapshot=1 su ${PGUSER} -c "dropdb ${TESTDB}" echo "INFO: enabling snapshots" else echo "INFO: create database failed for snapshots - dumping databases directly" fi sSqlGetDblist="select datname from pg_database where not datistemplate and datallowconn order by datname;" for DATABASE in $( su ${PGUSER} -c "psql ${BACKUP_PARAMS} -At -c '$sSqlGetDblist' postgres" 2>/dev/null | grep -v "^$snapshotprefix" ) do echo -n "__DB__${SERVICENAME} backup $DATABASE ... " bUseSnapshot4DB=$bUseSnapshot SNAPSHOTDB="${DATABASE}" test $bUseSnapshot4DB -eq 1 && SNAPSHOTDB="${snapshotprefix}${DATABASE}" OUTFILE="${BACKUP_TARGETDIR}/$(get_outfile ${DATABASE}).sql" myrc=0 # drop snapshot db first - just in case if [ $bUseSnapshot4DB -eq 1 ]; then echo -n " snapshot ... " su ${PGUSER} -c "dropdb ${SNAPSHOTDB}" >/dev/null 2>&1 if ! su ${PGUSER} -c "psql ${BACKUP_PARAMS} -c \"CREATE DATABASE ${SNAPSHOTDB} WITH TEMPLATE ${DATABASE};\"" >/dev/null 2>&1; then echo -n " nope, using origin ... " bUseSnapshot4DB=0 SNAPSHOTDB="${DATABASE}" fi fi if [ $myrc -eq 0 ]; then echo -n "backup ... " if su ${PGUSER} -c "pg_dump ${BACKUP_PARAMS} -Fp ${SNAPSHOTDB} >$OUTFILE"; then fetchrc >/dev/null test $bUseSnapshot4DB -eq 1 && ( echo -n "delete snapshot ... " su ${PGUSER} -c "dropdb ${SNAPSHOTDB}" ) db._compressDumpfile "$OUTFILE" else fetchrc test $bUseSnapshot4DB -eq 1 && su ${PGUSER} -c "dropdb ${SNAPSHOTDB}" fi else cecho error "ERROR!" fi done ) } # restore database dump file into database # param string database dump file (gzipped) # param string optional: database to import; default: database is parsed from file function pgsql.restore(){ sMyfile=$1 sMyDb=$2 if [ -z "$sMyDb" ]; then h2 "analyze dump $sMyfile" sMyDb="$(guessDB "$sMyfile" )" echo "detected db schema from file: [${sMyDb}]" else echo "db schema from param 2: [${sMyDb}]" fi echo echo import to "$sMyDb"... h2 "deleting database [$sMyDb] ..." color cmd su ${PGUSER} -c "dropdb ${sMyDb}" color reset h2 "ensure that database exists ..." color cmd su ${PGUSER} -c "psql ${BACKUP_PARAMS} -c \"CREATE DATABASE ${sMyDb};\"" fetchrc color reset h2 "import ..." ls -l "${sMyfile}" echo "import to database [${sMyDb}]" color cmd zcat "${sMyfile}" | su ${PGUSER} -c "psql ${BACKUP_PARAMS} -d ${sMyDb}" fetchrc color reset } # -------------------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------------------- # ----- requirements j_requireBinary "psql" 1 if [ $rc -ne 0 ]; then color.echo error "ERROR: Missing psql binary. Your Sqlite data cannot be dumped." else action=$1 shift 1 "${SERVICENAME}.$action" $* fi echo "__DB__$SERVICENAME INFO: $0 $* [$SERVICENAME] final returncode rc=$rc" # --------------------------------------------------------------------------------