From: Frank Brehm Date: Wed, 15 Nov 2017 17:47:57 +0000 (+0100) Subject: Adding bin/backup_pgsql.sh X-Git-Tag: 0.1.2~81 X-Git-Url: https://git.uhu-banane.de/?a=commitdiff_plain;h=9b2ee2e0706fcc6a2061f8f0f49a6352d35e45c6;p=pixelpark%2Fadmin-tools.git Adding bin/backup_pgsql.sh --- diff --git a/bin/backup_pgsql.sh b/bin/backup_pgsql.sh new file mode 100755 index 0000000..19127ab --- /dev/null +++ b/bin/backup_pgsql.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash + +########################### +# REQUIREMENTS +########################### +# +# * Required commands: +# + pg_dump +# + du +# + tee +# + bzip2 # If bzip2 is not available, change 'CMD_COMPRESS' +# # to use 'gzip' or whatever compress command you want. +# + +########################### +# USAGE +########################### +# +# * It stores all backup copies in directory '/var/vmail/backup' by default, +# You can change it in variable $BACKUP_ROOTDIR below. +# +# * Set correct values for below variables: +# +# PGSQL_SYS_USER +# BACKUP_ROOTDIR +# DATABASES +# +# * Add crontab job for root user (or whatever user you want): +# +# # crontab -e -u root +# 1 4 * * * bash /path/to/backup_pgsql.sh +# +# * Make sure 'crond' service is running. +# + +set -e +set -u + +export LC_ALL=C +export LANG=C + +######################################################### +# Modify below variables to fit your need ---- +######################################################### +# Keep backup for how many days. Default is 90 days. +KEEP_DAYS='90' + +# System user used to run PostgreSQL daemon. +# - On Linux, it's postgres. +# - On FreeBSD, it's pgsql. +# - On OpenBSD, it's _postgresql. +export PGSQL_SYS_USER="postgres" + +# Where to store backup copies. +export BACKUP_ROOTDIR="/var/backup" + +export SUDO="" +if [[ "$( id -u -n )" != "${PGSQL_SYS_USER}" ]] ; then + export SUDO="sudo -i -u ${PGSQL_SYS_USER} " +fi + +# Detect existing databases +export DATABASES="$( ${SUDO}psql --list --tuples-only --no-align --no-readline --expanded --field-separator=',' | grep -i '^Name' | awk -F ',' '{print $2}' )" + +export PATH='/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin' + +# Commands. +export CMD_DATE='/bin/date' +export CMD_DU='du -sk' +export CMD_COMPRESS='bzip2 -9' +export COMPRESS_SUFFIX='bz2' +export CMD_PG_DUMP='pg_dump' + +# Date. +export YEAR="$(${CMD_DATE} +%Y)" +export MONTH="$(${CMD_DATE} +%m)" +export DAY="$(${CMD_DATE} +%d)" +export TIME="$(${CMD_DATE} +%H:%M:%S)" +export TIMESTAMP="${YEAR}-${MONTH}-${DAY}-${TIME}" + +# Pre-defined backup status +export BACKUP_SUCCESS='YES' + +# Define, check, create directories. +export BACKUP_DIR="${BACKUP_ROOTDIR}/pgsql/${YEAR}/${MONTH}/${DAY}" + +# Find the old backup which should be removed. +export REMOVE_OLD_BACKUP='NO' +if which python &>/dev/null; then + export REMOVE_OLD_BACKUP='YES' + py_cmd="import time; import datetime; t=time.localtime(); print datetime.date(t.tm_year, t.tm_mon, t.tm_mday) - datetime.timedelta(days=${KEEP_DAYS})" + shift_date=$(python -c "${py_cmd}") + shift_year="$(echo ${shift_date} | awk -F'-' '{print $1}')" + shift_month="$(echo ${shift_date} | awk -F'-' '{print $2}')" + shift_day="$(echo ${shift_date} | awk -F'-' '{print $3}')" + export REMOVED_BACKUP_DIR="${BACKUP_ROOTDIR}/pgsql/${shift_year}/${shift_month}/${shift_day}" +fi + +# Log file +export LOGFILE="${BACKUP_DIR}/${TIMESTAMP}.log" + +# Check and create directories. +if [[ ! -d "${BACKUP_DIR}" ]] ; then + ${SUDO}mkdir -p "${BACKUP_DIR}" +fi + +# Get HOME directory of PGSQL_SYS_USER +export PGSQL_SYS_USER_HOME=$( getent passwd "${PGSQL_SYS_USER}" | awk -F':' '{print $6}' ) + +# Initialize log file. +echo "* Starting at: ${YEAR}-${MONTH}-${DAY}-${TIME}." | ${SUDO}tee ${LOGFILE} +echo "* Backup directory: ${BACKUP_DIR}." | ${SUDO}tee -a ${LOGFILE} + +TMP_DIR=$( ${SUDO}mktemp -d -p "${PGSQL_SYS_USER_HOME}" backup.XXXXXXXX.d ) + +cleanup_tmp_dir() { + ${SUDO}rm -rf "${TMP_DIR}" +} + +trap cleanup_tmp_dir INT TERM EXIT ABRT + +# Backup. +echo "* Backing up databases: ${DATABASES}." | ${SUDO}tee -a ${LOGFILE} +for db in ${DATABASES}; do + + output_sql="${db}-${TIMESTAMP}.sql" + out_sql_tmp="${TMP_DIR}/${output_sql}" + out_sql_tgt="${BACKUP_DIR}/${output_sql}" + +# # Check database existence +# if ${SUDO}"psql -d ${db} -c '\q' >/dev/null 2>&1" ; then +# : +# else +# echo "Database '${db}' does not exists." | ${SUDO}tee -a ${LOGFILE} +# continue +# fi + + # Dump + ${SUDO}"${CMD_PG_DUMP}" ${db} | ${SUDO}tee "${out_sql_tmp}" >/dev/null + + # Move to backup directory. + ${SUDO}mv "${out_sql_tmp}" ${BACKUP_DIR} + + cd ${BACKUP_DIR} + + # Get original SQL file size + original_size="$(${CMD_DU} ${output_sql} | awk '{print $1}')" + echo " Original size ${output_sql}: ${original_size}" | ${SUDO}tee -a ${LOGFILE} + + # Compress + ${SUDO}${CMD_COMPRESS} ${out_sql_tgt} 2>&1 | ${SUDO}tee -a ${LOGFILE} + + ${SUDO}rm -f ${out_sql_tgt} | ${SUDO}tee -a ${LOGFILE} + echo -e " + ${db} [DONE]" | ${SUDO}tee -a ${LOGFILE} + +done + +# Append file size of backup files. +echo -e "* File size:\n----" | ${SUDO}tee -a ${LOGFILE} +${SUDO}${CMD_DU} ${BACKUP_DIR}/*${TIMESTAMP}*sql* | ${SUDO}tee -a ${LOGFILE} +echo "----" | ${SUDO}tee -a ${LOGFILE} + +echo "* Backup completed (Success? ${BACKUP_SUCCESS})." | ${SUDO}tee -a ${LOGFILE} + +if [[ "${BACKUP_SUCCESS}" == 'YES' ]]; then + echo -e "\n[OK] Backup successfully completed.\n" +else + echo -e "\n[ERROR] Backup completed with ERRORS.\n" >&2 +fi + +if [[ "${REMOVE_OLD_BACKUP}" == 'YES' && -d "${REMOVED_BACKUP_DIR}" ]]; then + echo -e "* Delete old backup: ${REMOVED_BACKUP_DIR}." | ${SUDO}tee -a ${LOGFILE} + echo -e "* Suppose to delete: ${REMOVED_BACKUP_DIR}" | ${SUDO}tee -a ${LOGFILE} + ${SUDO}rm -rf ${REMOVED_BACKUP_DIR} 2>&1 | ${SUDO}tee -a ${LOGFILE} +fi + +echo "* Backup log: ${LOGFILE}:" + + +# vim: ts=4 et list