Import postgresql plugin

This commit is contained in:
Marek Miklewicz
2026-07-04 16:00:04 +02:00
commit ddc971567f
74 changed files with 18735 additions and 0 deletions
+226
View File
@@ -0,0 +1,226 @@
#!/bin/bash
# =============================================================================
# postgres_backup.sh
# Backup wszystkich baz PostgreSQL na serwerze
#
# Przeznaczenie: cron (nie interaktywny)
# Wymagania: pg_dump, psql, dostęp do pliku poświadczeń (format pgpass)
#
# Przywracanie pojedynczej bazy:
# psql -h localhost -U postgres -d postgres -f nazwa_bazy.sql
# gunzip -c nazwa_bazy.sql.gz | psql -h localhost -U postgres -d postgres
# =============================================================================
# =============================================================================
# KONFIGURACJA
# =============================================================================
BASE_DIR="/home/admin/postgres_backup"
# Format daty katalogu backupu (składnia date +FORMAT)
DATE_FORMAT="%d-%m-%Y"
# 1 = dodaj godzinę i minuty do nazwy katalogu (np. 19-02-2026_14-35)
ADD_TIME=0
# Liczba dni przechowywania backupów (0 = bez automatycznego usuwania)
RETENTION=7
# 1 = kompresuj do .sql.gz | 0 = zostawiaj jako .sql
ENABLE_COMPRESSION=1
# Plik poświadczeń w formacie pgpass: host:port:database:user:password
# Musi mieć uprawnienia 600 lub 400
CREDENTIALS_FILE="/usr/local/directadmin/conf/postgresql.conf"
# Bazy wykluczone z backupu (oddzielone spacją)
EXCLUDE_DBS="template0 template1"
# =============================================================================
# WEWNĘTRZNA KONFIGURACJA nie zmieniaj
# =============================================================================
LOCK_FILE="/var/run/postgres_backup.lock"
LOG_FILE="/var/log/postgres_backup.log"
# =============================================================================
# INICJALIZACJA
# =============================================================================
set -uo pipefail
# Kolory tylko na terminalu
if [[ -t 1 ]]; then
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
else
RED=''; GREEN=''; YELLOW=''; NC=''
fi
ts() { date '+%Y-%m-%d %H:%M:%S'; }
log() { echo "[$(ts)] $*" | tee -a "$LOG_FILE"; }
ok() { echo -e "${GREEN}[OK]${NC} [$(ts)] $*" | tee -a "$LOG_FILE"; }
warn() { echo -e "${YELLOW}[WARN]${NC} [$(ts)] $*" | tee -a "$LOG_FILE"; }
die() { echo -e "${RED}[BŁĄD]${NC} [$(ts)] $*" | tee -a "$LOG_FILE" >&2; cleanup; exit 1; }
cleanup() { rm -f "$LOCK_FILE"; }
trap cleanup EXIT INT TERM
# ---------------------------------------------------------------------------
# Blokada przed równoległym uruchomieniem
# ---------------------------------------------------------------------------
if [[ -f "$LOCK_FILE" ]]; then
OLD_PID=$(cat "$LOCK_FILE" 2>/dev/null || echo "")
if [[ -n "$OLD_PID" ]] && kill -0 "$OLD_PID" 2>/dev/null; then
die "Backup jest już uruchomiony (PID: ${OLD_PID}). Przerywam."
fi
warn "Stały plik blokady (PID ${OLD_PID} nie istnieje) usuwam i kontynuuję."
rm -f "$LOCK_FILE"
fi
echo $$ > "$LOCK_FILE"
# ---------------------------------------------------------------------------
# Weryfikacja pliku poświadczeń
# ---------------------------------------------------------------------------
[[ -f "$CREDENTIALS_FILE" ]] \
|| die "Brak pliku poświadczeń: ${CREDENTIALS_FILE}"
_perms=$(stat -c '%a' "$CREDENTIALS_FILE")
[[ "$_perms" == "600" || "$_perms" == "400" ]] \
|| die "Plik ${CREDENTIALS_FILE} ma zbyt otwarte uprawnienia (${_perms}). Wymagane: 600 lub 400."
# Parsowanie: host:port:database:user:password
_line=$(head -1 "$CREDENTIALS_FILE")
PGHOST=$(echo "$_line" | cut -d: -f1)
PGPORT=$(echo "$_line" | cut -d: -f2)
PGUSER=$(echo "$_line" | cut -d: -f4)
[[ -n "$PGHOST" && -n "$PGPORT" && -n "$PGUSER" ]] \
|| die "Nieprawidłowy format pliku poświadczeń. Oczekiwany: host:port:database:user:password"
# Hasło przekazywane przez PGPASSFILE nie pojawia się w środowisku ani linii poleceń
export PGPASSFILE="$CREDENTIALS_FILE"
# ---------------------------------------------------------------------------
# Katalog backupu
# ---------------------------------------------------------------------------
if [[ "$ADD_TIME" == "1" ]]; then
DATE_STR=$(date +"${DATE_FORMAT}_%H-%M")
else
DATE_STR=$(date +"${DATE_FORMAT}")
fi
BACKUP_DIR="${BASE_DIR}/${DATE_STR}"
mkdir -p "$BACKUP_DIR" || die "Nie można utworzyć katalogu backupu: ${BACKUP_DIR}"
# =============================================================================
# BACKUP
# =============================================================================
log "================================================================="
log "Rozpoczęcie backupu PostgreSQL"
log "Host: ${PGHOST}:${PGPORT} Użytkownik: ${PGUSER}"
log "Katalog: ${BACKUP_DIR}"
log "Kompresja: ${ENABLE_COMPRESSION} Retencja: ${RETENTION} dni"
log "================================================================="
# ---------------------------------------------------------------------------
# Globals: użytkownicy, role, hasła, przynależności (pg_dumpall --globals-only)
# Wymagane do pełnego disaster recovery przywróć jako pierwsze
# ---------------------------------------------------------------------------
ERRORS=0
BACKED_UP=0
GLOBALS_SUCCESS=true
if [[ "$ENABLE_COMPRESSION" == "1" ]]; then
GLOBALS_FILE="${BACKUP_DIR}/_globals.sql.gz"
pg_dumpall \
-h "$PGHOST" -p "$PGPORT" -U "$PGUSER" \
--no-password --globals-only --clean --if-exists \
2>>"$LOG_FILE" \
| gzip -9 > "$GLOBALS_FILE" \
|| GLOBALS_SUCCESS=false
else
GLOBALS_FILE="${BACKUP_DIR}/_globals.sql"
pg_dumpall \
-h "$PGHOST" -p "$PGPORT" -U "$PGUSER" \
--no-password --globals-only --clean --if-exists \
> "$GLOBALS_FILE" 2>>"$LOG_FILE" \
|| GLOBALS_SUCCESS=false
fi
if [[ "$GLOBALS_SUCCESS" == "true" ]]; then
SIZE=$(du -sh "$GLOBALS_FILE" 2>/dev/null | cut -f1)
ok "_globals → ${GLOBALS_FILE##*/} (${SIZE})"
else
warn "_globals: backup ról i użytkowników nie powiódł się plik usunięty."
rm -f "$GLOBALS_FILE"
ERRORS=$((ERRORS + 1))
fi
# Lista baz danych
DATABASES=$(
psql -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" \
--no-password -t -A \
-c "SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname;" \
2>>"$LOG_FILE"
) || die "Nie można pobrać listy baz. Sprawdź połączenie i poświadczenia."
# Zbuduj wzorzec wykluczeń
EXCLUDE_PATTERN=$(echo "$EXCLUDE_DBS" | tr ' ' '|')
for DB in $DATABASES; do
# Pomiń wykluczone
if echo "$DB" | grep -qE "^(${EXCLUDE_PATTERN})$"; then
continue
fi
SUCCESS=true
if [[ "$ENABLE_COMPRESSION" == "1" ]]; then
OUT_FILE="${BACKUP_DIR}/${DB}.sql.gz"
pg_dump \
-h "$PGHOST" -p "$PGPORT" -U "$PGUSER" \
--no-password --create --clean --if-exists \
-F p "$DB" 2>>"$LOG_FILE" \
| gzip -9 > "$OUT_FILE" \
|| SUCCESS=false
else
OUT_FILE="${BACKUP_DIR}/${DB}.sql"
pg_dump \
-h "$PGHOST" -p "$PGPORT" -U "$PGUSER" \
--no-password --create --clean --if-exists \
-F p "$DB" > "$OUT_FILE" 2>>"$LOG_FILE" \
|| SUCCESS=false
fi
if [[ "$SUCCESS" == "true" ]]; then
SIZE=$(du -sh "$OUT_FILE" 2>/dev/null | cut -f1)
ok "${DB}${OUT_FILE##*/} (${SIZE})"
BACKED_UP=$((BACKED_UP + 1))
else
warn "${DB}: backup nie powiódł się plik usunięty."
rm -f "$OUT_FILE"
ERRORS=$((ERRORS + 1))
fi
done
log "Wynik: ${BACKED_UP} OK, ${ERRORS} błędów."
# =============================================================================
# RETENCJA
# =============================================================================
if [[ "$RETENTION" -gt 0 ]]; then
log "Usuwanie backupów starszych niż ${RETENTION} dni..."
find "$BASE_DIR" -maxdepth 1 -mindepth 1 -type d -mtime +"$RETENTION" \
-exec rm -rf {} + 2>/dev/null || true
fi
# =============================================================================
# ZAKOŃCZENIE
# =============================================================================
log "Backup zakończony."
[[ "$ERRORS" -eq 0 ]] || exit 1
exit 0