#!/bin/sh #----------------------------------------------------------------------------- # /var/install/bin/postgresql-tools-backup # # Copyright (c) 2005 Daniel Vogel # # Creation: 26.09.2005 dv # Last Update: $Id$ # # 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. #----------------------------------------------------------------------------- #include eislib . /var/install/include/eislib . /etc/config.d/postgresql PROG=/usr/local/pgsql/bin/pg_dump # --------------------------------------------------------------------------- # do mount (prior to backup) # --------------------------------------------------------------------------- exec_mount() { if [ -n "$POSTGRESQL_BACKUP_MOUNT" ] then eval ${POSTGRESQL_BACKUP_MOUNT} 2>&1 if [ "$?" -ne "0" ] then return 1 fi fi return 0 } # --------------------------------------------------------------------------- # do unmount (right after backup) # --------------------------------------------------------------------------- exec_unmount() { if [ -n "$POSTGRESQL_BACKUP_UMOUNT" ] then eval ${POSTGRESQL_BACKUP_UMOUNT} 2>&1 if [ "$?" -ne "0" ] then return 1 fi fi return 0 } # --------------------------------------------------------------------------- # execute database query # --------------------------------------------------------------------------- run_query() { echo "${1}" | \ /usr/local/pgsql/bin/psql template1 postgres -t -A } # --------------------------------------------------------------------------- # invoke ask to get user selection # --------------------------------------------------------------------------- get_selection() { _choice="${1}" _ask_file=$(mktemp -t .XXXXXXXXX) /var/install/bin/ask "Select" "" "${_choice}" "^$=Return" "0=Exit" \ > ${_ask_file} _rc=${?} SELINDEX=$(cat ${_ask_file}) rm -f ${_ask_file} if [ ${_rc} = 255 ] then return 127 fi case ${SELINDEX} in '') return 127 ;; 0) return 127 ;; *) return 0 ;; esac } # --------------------------------------------------------------------------- # main routine # --------------------------------------------------------------------------- if [ "$1" = "-auto" ] then MANUAL="false" else MANUAL="true" fi if [ "${MANUAL}" = "true" ] then clrhome # Mount backup media if ! exec_mount then echo "unable to execute: $POSTGRESQL_BACKUP_MOUNT" anykey exit 1 fi # ----------------------------------------------------------- # database selection # ----------------------------------------------------------- # get database for backup result=$(run_query "SELECT d.datname , u.usename , pg_catalog.pg_encoding_to_char(d.encoding) FROM pg_catalog.pg_database d LEFT JOIN pg_catalog.pg_user u ON d.datdba = u.usesysid ORDER BY 1;") # print table heading mecho --info "Select database for backup:" echo techo --begin '3 3r 1 15 1 10 1 10' techo --row "" --info "No" "" --info "Name" "" --info "Owner" "" --info "Encoding" echo # list databases old_ifs=${IFS} IFS=$'\x0A' idx=0 for line in ${result} do idx=$(/usr/bin/expr ${idx} + 1) dbname=$(echo ${line} | cut -d\| -f1) dbowner=$(echo ${line} | cut -d\| -f2) dbencode=$(echo ${line} | cut -d\| -f3) techo --row "" "${idx}" "" "${dbname}" "" "${dbowner}" "" "${dbencode}" eval 'DATABASE_'${idx}'_NAME'="${dbname}" done techo --end echo IFS=${old_ifs} # get user selection -> SELINDEX (using global SELINDEX is ugly but # necessary to prevent input/output error when Ctrl+C is hit) get_selection "1-${idx}" if [ "${?}" != "0" ] then exit "${?}" else eval database='$DATABASE_'${SELINDEX}'_NAME' fi # show result echo mecho -n --info "Selected database: " mecho "${database}" echo echo # ----------------------------------------------------------- # database user selection # ----------------------------------------------------------- # get database user result=$(run_query "SELECT usename FROM pg_user;") # print table heading mecho --info "Select database user for backup:" echo techo --begin '3 3r 1 15' techo --row "" --info "No" "" --info "Name" echo # list databases old_ifs=${IFS} IFS=$'\x0A' idx=0 for line in ${result} do idx=$(/usr/bin/expr ${idx} + 1) dbuser=$(echo ${line} | cut -d\| -f1) techo --row "" "${idx}" "" "${dbuser}" eval 'DATABASE_'${idx}'_USER'="${dbuser}" done techo --end echo IFS=${old_ifs} # get user selection -> SELINDEX (using global SELINDEX is ugly but # necessary to prevent input/output error when Ctrl+C is hit) get_selection "1-${idx}" if [ "${?}" != "0" ] then exit "${?}" else eval dbuser='$DATABASE_'${SELINDEX}'_USER' fi # show result echo mecho -n --info "Selected database user: " mecho "${dbuser}" echo echo # get for OK ;-), last out from backupp _ask_file=$(mktemp -t .XXXXXXXXX) /var/install/bin/ask "Continue" "y" >${_ask_file} rc=${?} _ok_to_backup=$(cat ${_ask_file}) rm -f ${_ask_file} if [ ${rc} = 255 ] then exit 127 fi case ${_ok_to_backup} in no) exit 0 ;; esac # ----------------------------------------------------------- # do backup of selected database # ----------------------------------------------------------- if [ -z "$dbuser" ] then dbuser='postgres' fi # make sure backup dir exists mkdir -p "$POSTGRESQL_BACKUP_TARGET" 2>&1 >/dev/null # create new filename backupfile="$database-`/bin/date +%Y-%m-%d-%H%M%S`.backup" backupfile="$POSTGRESQL_BACKUP_TARGET/$backupfile" # perform backup echo -n "Backup of database $database... " $PROG -i -U "$dbuser" -F c -b -v -f "$backupfile" $database if [ "$?" = "0" ] then echo echo "Backup completed successfully!" echo else echo echo "Backup failed!" echo fi # Unount if ! exec_unmount then echo "unable to execute: $POSTGRESQL_BACKUP_UMOUNT" fi anykey exit 0 else # initialize error counter errcount=0 { # Mount if ! exec_mount then errcount=`/usr/bin/expr $errors + 1` fi if [ "$errcount" -eq "0" ] then # make sure backup dir exists mkdir -p "$POSTGRESQL_BACKUP_TARGET" 2>&1 >/dev/null # perform all backups idx=1 while [ "$idx" -le "$POSTGRESQL_BACKUP_N" ] do eval database='$POSTGRESQL_BACKUP_'$idx'_DBNAME' eval dbuser='$POSTGRESQL_BACKUP_'$idx'_USER' eval maxfiles='$POSTGRESQL_BACKUP_'$idx'_MAX' # reduce backup files to configured limit if [ "$maxfiles" -lt "1" ] then maxfiles='1' fi maxfiles=`/usr/bin/expr $maxfiles - 1` backup_files=`/bin/ls -t "$POSTGRESQL_BACKUP_TARGET/"$database-*.backup 2>/dev/null` c='0' for file in $backup_files do if [ "$c" -ge "$maxfiles" ] then rm "$file" fi c=`/usr/bin/expr $c + 1` done # create new filename backupfile="$database-`/bin/date +%Y-%m-%d-%H%M%S`.backup" backupfile="$POSTGRESQL_BACKUP_TARGET/$backupfile" # perform backup echo -n "Backup of database $database... " $PROG -i -U "$dbuser" -F c -b -f "$backupfile" $database 2> /tmp/pg_dump$$.log if [ "$?" = "0" ] then echo "ok" else echo "failed" echo echo "Error report:" cat /tmp/pg_dump$$.log echo errcount=`/usr/bin/expr $errcount + 1` fi rm /tmp/pg_dump$$.log # count idx=`/usr/bin/expr $idx + 1` done # Unount if ! exec_unmount then errcount=`/usr/bin/expr $errcount + 1` fi fi } > /tmp/backup-$$.log if [ -f "/tmp/backup-$$.log" ] then if [ -n "$POSTGRESQL_BACKUP_NOTIFY" -a "$errcount" -gt "0" ] then SENDMAIL='/usr/sbin/sendmail' full_domain="$(hostname -f)" . /var/install/include/eistime { echo "From: PostgreSQL Agent " echo "To: <${POSTGRESQL_BACKUP_NOTIFY}>" echo "Subject: PostgreSQL database backup service on Server '${HOSTNAME}'" echo "Mime-Version: 1.0" echo "X-Mailer: sendmail PostgreSQL on eisfair" echo "Content-Type: text/plain; charset=us-ascii" echo "Content-Transfer-Encoding: 8bit" echo echo echo "Dispatched from PostgreSQL Agent on Server '${HOSTNAME}'" echo "Current Date: ${EISDATE} Time: ${EISTIME}" echo cat /tmp/backup-$$.log } | ${SENDMAIL} ${POSTGRESQL_BACKUP_NOTIFY} fi rm /tmp/backup-$$.log fi fi