#!/usr/bin/env bash # # Create a compressed PostgreSQL backup and remove old backup files. # # Required environment variables: # PGHOST PostgreSQL host. # PGUSER PostgreSQL user. # PGPASSWORD PostgreSQL password. # PGDATABASE Database name to back up. # # Usage: # PGHOST=localhost PGUSER=app PGPASSWORD=secret PGDATABASE=appdb \ # bash postgres_backup.sh --destination /backups/postgres # # Options: # --destination DIR Backup directory. Default: ./backups # --retention-days N Delete backups older than N days. Default: 14. # --help Show this help message. set -Eeuo pipefail destination="./backups" retention_days="14" usage() { sed -n '2,24p' "$0" | sed 's/^# \{0,1\}//' } log() { printf '[%s] %s\n' "$(date -Is)" "$*" } require_env() { local name="$1" if [[ -z "${!name:-}" ]]; then printf 'ERROR: required environment variable is missing: %s\n' "$name" >&2 exit 1 fi } while [[ "$#" -gt 0 ]]; do case "$1" in --destination) destination="${2:-}" [[ -n "$destination" ]] || { printf 'ERROR: --destination requires a directory.\n' >&2; exit 1; } shift 2 ;; --retention-days) retention_days="${2:-}" [[ "$retention_days" =~ ^[0-9]+$ ]] || { printf 'ERROR: retention must be a positive integer.\n' >&2; exit 1; } shift 2 ;; --help|-h) usage exit 0 ;; *) printf 'ERROR: unknown option: %s\n' "$1" >&2 usage >&2 exit 1 ;; esac done command -v pg_dump >/dev/null 2>&1 || { printf 'ERROR: pg_dump command not found.\n' >&2; exit 1; } command -v gzip >/dev/null 2>&1 || { printf 'ERROR: gzip command not found.\n' >&2; exit 1; } require_env PGHOST require_env PGUSER require_env PGPASSWORD require_env PGDATABASE mkdir -p "$destination" timestamp="$(date +%Y%m%d-%H%M%S)" backup_file="${destination}/${PGDATABASE}-${timestamp}.sql.gz" log "Starting PostgreSQL backup for database '${PGDATABASE}'." pg_dump --format=plain --no-owner --no-privileges "$PGDATABASE" | gzip -9 > "$backup_file" if [[ ! -s "$backup_file" ]]; then printf 'ERROR: backup file was not created or is empty: %s\n' "$backup_file" >&2 exit 1 fi log "Backup created: ${backup_file}" log "Removing backups older than ${retention_days} days from ${destination}." find "$destination" -type f -name "${PGDATABASE}-*.sql.gz" -mtime "+${retention_days}" -print -delete log "Backup job completed successfully."