From 3808efdbddcf2e9bfa2ab53a6ae22d46ccdc245f Mon Sep 17 00:00:00 2001 From: Paulo Nonato Date: Sat, 18 Apr 2026 23:31:21 -0300 Subject: [PATCH] Add scripts/postgres_backup.sh --- scripts/postgres_backup.sh | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 scripts/postgres_backup.sh diff --git a/scripts/postgres_backup.sh b/scripts/postgres_backup.sh new file mode 100644 index 0000000..25a183d --- /dev/null +++ b/scripts/postgres_backup.sh @@ -0,0 +1,90 @@ +#!/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." +