#!/bin/sh #----------------------------------------------------------------------------- # /var/install/bin/postgresql-common-backup-db # # Creation: 2019-03-24 dv # Last Update: 2023-07-23 09:11:10 # # Copyright (c) 2024 the eisfair team, team(at)eisfair(dot)org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. #----------------------------------------------------------------------------- . /var/install/include/eislib . /var/install/bin/postgresql-common-browser-helpers #----------------------------------------------------------------------------- # show help on arguments and possible options # @param n/a # @return n/a #----------------------------------------------------------------------------- show_help() { cat < name of database to backup [postgres] --user= database user [postgres] --mount= action to perform before backup --umount= action to perform after backup --folder= output folder [/tmp] --file-limit= limit the number of backup files --prefix= file prefix for backup files [pgsql] --port= database service port [5432] --bin-dir= path where postgresql tools reside [/usr/bin] --interactive query database and user interactively EOF } # --------------------------------------------------------------------------- # move the cursor to the specified screen position # @param $1 X cursor position # @param $2 Y cursor position # @return n/a # --------------------------------------------------------------------------- gotoxy() { echo -e "\033[$2;$1H\c"; } # --------------------------------------------------------------------------- # execute database query # @param query to execute # --------------------------------------------------------------------------- run_query() { echo "${1}" | \ ${bin_dir}/psql -p "${port}" template1 postgres -t -A } # --------------------------------------------------------------------------- # connect to server and query version # @return 0 on success, 1 on failure # --------------------------------------------------------------------------- identify_server() { local result=$(run_query "SELECT version();") if [ "${?}" -eq "0" ] then server=$(echo ${result} | cut -d\| -f1) server=$(echo ${server} | cut -d\, -f1) return 0 fi return 1 } # --------------------------------------------------------------------------- # setup the file name for backup archive # --------------------------------------------------------------------------- setup_backup_filename() { backupfile="${prefix}-${database}-$(/bin/date +%Y-%m-%d-%H%M%S).backup" } # --------------------------------------------------------------------------- # wait for user to acknowledge settings done by previous steps # @return 0 on success, 1 if used did abort, 127 if user wants to exit menu # --------------------------------------------------------------------------- user_acknowledge() { clrhome # print table heading mecho --info "DATABASE BACKUP - ${server}" echo mecho --info "STEP 3: Final Acknowledgement:" echo echo "If you proceed, the following settings will be used" echo "to perform the backup:" echo # print summary of settings mecho --info -n "Database: " echo "${database}" mecho --info -n "Database User: " echo "${user}" mecho --info -n "Backup File: " echo "${backupfile}" mecho --info -n "Backup Folder: " echo "${folder}" echo # get final acknowledge local ask_file=$(mktemp -t .XXXXXXXXX) local rc local ok_to_backup /var/install/bin/ask "Continue" "y" >${ask_file} rc=${?} ok_to_backup=$(cat ${ask_file}) rm -f ${ask_file} if [ ${rc} = 255 ] then return 127 fi if [ "${ok_to_backup}" = "yes" ] then return 0 else return 1 fi } # --------------------------------------------------------------------------- # perform optional mount operation # @return 0 on success, 1 in case of error # --------------------------------------------------------------------------- perform_mount() { if [ -n "${mount_cmd}" ] then eval ${mount_cmd} 2>&1 if [ "$?" -ne "0" ] then echo "error: failed to mount backup volume!" >&2 return 1 fi fi return 0 } # --------------------------------------------------------------------------- # perform optional unmount operation # @return 0 on success, 1 in case of error # --------------------------------------------------------------------------- perform_umount() { # do umount step if required if [ -n "${umount_cmd}" ] then eval ${umount_cmd} 2>&1 if [ "$?" -ne "0" ] then echo "error: failed to unmount backup volume!" >&2 return 1 fi fi } # --------------------------------------------------------------------------- # perform database backup # @return 0 on success, 1 in case of error # --------------------------------------------------------------------------- perform_backup() { clrhome mecho --info "DATABASE BACKUP - ${server}" echo # print table heading if [ "${interactive}" = "yes" ] then mecho --info "STEP 4: Backup of database ${database}:" echo else mecho --info "Backup of database ${database}:" echo fi # perform backup ${bin_dir}/pg_dump \ -p "${port}" \ -U "${user}" \ -F c -b -v \ --quote-all-identifiers \ -f "${folder}/${backupfile}" ${database} if [ "${?}" = "0" ] then mecho mecho --info "Backup succeeded!" mecho return 0 else mecho mecho --error "Backup failed!" mecho rm -f "${folder}/${backupfile}" return 1 fi } # --------------------------------------------------------------------------- # limit the max number of files # --------------------------------------------------------------------------- limit_files() { local files=$(/bin/ls -t "${folder}/${prefix}-${database}-"*.backup 2>/dev/null) local count="0" local file for file in ${files} do if [ "${count}" -ge "${file_limit}" ] then rm "${file}" fi count=$((${count} + 1)) done } # --------------------------------------------------------------------------- # main routine # --------------------------------------------------------------------------- main() { interactive="no" port="5432" user="postgres" database="postgres" folder="/tmp" prefix="pgsql" bin_dir="/usr/bin" file_limit="0" # read option switches while [ "${1:0:2}" = "--" ] do case ${1} in --help) show_help exit 0 ;; --bin-dir) shift bin_dir="${1}" shift ;; --bin-dir=*) bin_dir="${1:10}" shift ;; --database) shift database="${1}" shift ;; --database=*) database="${1:11}" shift ;; --user) shift user="${1}" shift ;; --user=*) user="${1:7}" shift ;; --mount) shift mount_cmd="${1}" shift ;; --mount=*) mount_cmd="${1:8}" shift ;; --umount) shift umount_cmd="${1}" shift ;; --umount=*) umount_cmd="${1:9}" shift ;; --folder) shift folder="${1}" shift ;; --folder=*) folder="${1:9}" shift ;; --file-limit) shift file_limit="${1}" shift ;; --file-limit=*) file_limit="${1:13}" shift ;; --port) shift port="${1}" shift ;; --port=*) port="${1:7}" shift ;; --prefix) shift prefix="${1}" shift ;; --prefix=*) prefix="${1:9}" shift ;; --interactive) interactive="yes" shift ;; *) echo "error: invalid option switch \"$1\"!" >&2 exit 1 ;; esac done if [ "$#" -gt "0" ] then echo "error: invalid option switch \"$1\"!" >&2 exit 1 fi # fetch version from server if ! identify_server then exit 1 fi # if interactive mode was selected, ask values from user if [ "${interactive}" = "yes" ] then browse_databases \ "DATABASE BACKUP - ${server}" \ "STEP 1: Select database to backup:" \ "no" \ "database" rc="${?}" if [ "${rc}" -ne "0" ] then exit ${rc} fi browse_users \ "DATABASE BACKUP - ${server}" \ "STEP 2: Select database user to perform the backup:" \ "user" rc="${?}" if [ "${rc}" -ne "0" ] then exit ${rc} fi setup_backup_filename if ! user_acknowledge then exit 0 fi else setup_backup_filename fi # do mount step if required if ! perform_mount then exit 1 fi # create backup folder (if not already present) mkdir -p "${folder}" 2>&1 >/dev/null # preform the backup if ! perform_backup then perform_umount exit 1 fi # limit the number of backup files if [ "${file_limit}" -gt "0" ] then limit_files fi # do umount step if required if ! perform_umount then exit 1 fi } # --------------------------------------------------------------------------- # call function main # --------------------------------------------------------------------------- main "${@}" exit 0 # --------------------------------------------------------------------------- # end # ---------------------------------------------------------------------------