ferrero-opentext/Python-Version/database/check_backups.sh
DJP e0128d98b8 Add automated PostgreSQL backup and restore system
Implements dual backup strategy with daily SQL dumps and weekly binary
backups, complete with restore capabilities and health monitoring.

Backup System Components:

1. database/backup.sh:
   - Daily mode: pg_dump SQL dumps (7-day retention)
   - Weekly mode: pg_basebackup binary backup (latest only)
   - Automatic cleanup of old backups
   - Compression (gzip) for space efficiency
   - Email notifications on failures
   - Docker-compatible execution

2. database/restore.sh:
   - Restore from SQL dump backups
   - Safety backup before restore
   - Confirmation prompts
   - Validation and verification
   - List available backups

3. database/check_backups.sh:
   - Health check monitoring
   - Verifies latest backup age (warns if > 25 hours)
   - Displays backup counts and sizes
   - Quiet mode for cron automation
   - Lists all available backups

Documentation:

- DATABASE_BACKUP_GUIDE.md: Complete backup/restore guide
  - Automated cron setup
  - Manual backup procedures
  - Restore scenarios
  - Troubleshooting
  - Disk space management

- backups/README.md: Quick reference
  - Directory structure
  - Common commands
  - Retention policy
  - Security notes

Configuration:

- Updated .gitignore to exclude backup files
- Backup locations: backups/dumps/, backups/basebackups/
- Logs: logs/backup.log, logs/restore.log
- Retention: 7 daily dumps + 1 weekly basebackup

Cron Schedule (Production):
- Daily: 2:00 AM (pg_dump)
- Weekly: Sundays 3:00 AM (pg_basebackup)
- Health Check: 8:00 AM daily

Features:
 Automated daily and weekly backups
 Dual strategy (logical + physical)
 Space-efficient (7-day retention, ~50 MB total)
 Safety backups before restore
 Email alerts on failures
 Health monitoring
 Docker-compatible
 Tested locally

Testing Performed:
- Daily backup created successfully (77K compressed)
- Backup file integrity verified (gzip test passed)
- Health check shows "Backup system healthy"
- Restore --list command working
- All scripts executable and functional

Disk Usage Estimate:
- Daily dumps: 7 × ~2 MB = ~14 MB
- Weekly backup: 1 × ~30 MB = ~30 MB
- Total: ~50 MB maximum

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 17:30:10 -05:00

186 lines
4.8 KiB
Bash
Executable file

#!/bin/bash
#
# Database Backup Health Check Script
# Verifies backup status and alerts if backups are stale or missing
#
# Usage:
# ./database/check_backups.sh # Check backup health
# ./database/check_backups.sh --quiet # Minimal output (for cron)
#
# Directories
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
BACKUP_BASE_DIR="$PROJECT_DIR/backups"
DUMP_DIR="$BACKUP_BASE_DIR/dumps"
BASEBACKUP_DIR="$BACKUP_BASE_DIR/basebackups"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
# Quiet mode
QUIET=false
if [ "$1" = "--quiet" ]; then
QUIET=true
fi
# Output function
output() {
if [ "$QUIET" = false ]; then
echo -e "$1"
fi
}
# Check if backups exist
check_daily_backups() {
output "${GREEN}Daily Backups (pg_dump):${NC}"
if [ ! -d "$DUMP_DIR" ]; then
output "${RED}✗ Backup directory not found: $DUMP_DIR${NC}"
return 1
fi
local backup_count=$(ls -1 "$DUMP_DIR"/*.sql.gz 2>/dev/null | wc -l)
if [ "$backup_count" -eq 0 ]; then
output "${RED}✗ No daily backups found${NC}"
return 1
fi
output "${GREEN}✓ Found $backup_count daily backup(s)${NC}"
# Find latest backup
local latest_backup=$(ls -t "$DUMP_DIR"/*.sql.gz 2>/dev/null | head -1)
if [ -n "$latest_backup" ]; then
local backup_age_hours=$(( ($(date +%s) - $(stat -f %m "$latest_backup")) / 3600 ))
local backup_size=$(du -h "$latest_backup" | cut -f1)
local backup_name=$(basename "$latest_backup")
output " Latest: $backup_name"
output " Size: $backup_size"
output " Age: ${backup_age_hours} hours ago"
if [ "$backup_age_hours" -gt 25 ]; then
output "${YELLOW} ⚠️ WARNING: Backup is older than 25 hours${NC}"
return 1
else
output "${GREEN} ✓ Backup is fresh${NC}"
fi
fi
output ""
return 0
}
check_weekly_backups() {
output "${GREEN}Weekly Backups (pg_basebackup):${NC}"
if [ ! -d "$BASEBACKUP_DIR" ]; then
output "${YELLOW}⚠️ Weekly backup directory not found (optional)${NC}"
return 0
fi
local backup_count=$(ls -1 "$BASEBACKUP_DIR"/*.tar.gz 2>/dev/null | wc -l)
if [ "$backup_count" -eq 0 ]; then
output "${YELLOW}⚠️ No weekly backups found (will be created on Sunday)${NC}"
return 0
fi
output "${GREEN}✓ Found $backup_count weekly backup(s)${NC}"
# Find latest backup
local latest_backup=$(ls -t "$BASEBACKUP_DIR"/*.tar.gz 2>/dev/null | head -1)
if [ -n "$latest_backup" ]; then
local backup_age_days=$(( ($(date +%s) - $(stat -f %m "$latest_backup")) / 86400 ))
local backup_size=$(du -h "$latest_backup" | cut -f1)
local backup_name=$(basename "$latest_backup")
output " Latest: $backup_name"
output " Size: $backup_size"
output " Age: ${backup_age_days} days ago"
fi
output ""
return 0
}
# Display disk space
check_disk_space() {
output "${GREEN}Disk Space Usage:${NC}"
if [ -d "$BACKUP_BASE_DIR" ]; then
local total_size=$(du -sh "$BACKUP_BASE_DIR" 2>/dev/null | cut -f1)
output " Total backup size: $total_size"
else
output "${YELLOW} Backup directory not yet created${NC}"
fi
output ""
}
# List all backups
list_all_backups() {
output "${GREEN}All Available Backups:${NC}"
output ""
if [ -d "$DUMP_DIR" ] && ls "$DUMP_DIR"/*.sql.gz 1> /dev/null 2>&1; then
output "Daily Backups:"
ls -lht "$DUMP_DIR"/*.sql.gz | head -10 | awk '{print " " $9 " - " $5 " - " $6 " " $7 " " $8}'
output ""
fi
if [ -d "$BASEBACKUP_DIR" ] && ls "$BASEBACKUP_DIR"/*.tar.gz 1> /dev/null 2>&1; then
output "Weekly Backups:"
ls -lht "$BASEBACKUP_DIR"/*.tar.gz | awk '{print " " $9 " - " $5 " - " $6 " " $7 " " $8}'
output ""
fi
}
# Main
main() {
if [ "$QUIET" = false ]; then
echo "========================================="
echo "Ferrero Database Backup Health Check"
echo "========================================="
echo ""
fi
local status=0
# Check daily backups
if ! check_daily_backups; then
status=1
fi
# Check weekly backups
check_weekly_backups
# Check disk space
check_disk_space
# List all backups if not quiet
if [ "$QUIET" = false ]; then
list_all_backups
fi
if [ "$QUIET" = false ]; then
echo "========================================="
if [ $status -eq 0 ]; then
echo -e "${GREEN}✓ Backup system healthy${NC}"
else
echo -e "${RED}✗ Backup system needs attention${NC}"
fi
echo "========================================="
fi
exit $status
}
# Run main
main