56 lines
1.6 KiB
Python
56 lines
1.6 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
PostgreSQL backup script for SeaFare Montana.
|
||
|
|
Run via cron or manually: python backup_db.py
|
||
|
|
|
||
|
|
Backs up the database to a timestamped SQL file.
|
||
|
|
Usage:
|
||
|
|
python backup_db.py # Backup to ./backups/
|
||
|
|
python backup_db.py /path/to/dir # Backup to specified dir
|
||
|
|
"""
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
import subprocess
|
||
|
|
from datetime import datetime
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from dotenv import load_dotenv
|
||
|
|
load_dotenv()
|
||
|
|
|
||
|
|
DATABASE_URL = os.environ.get('DATABASE_URL')
|
||
|
|
|
||
|
|
def backup():
|
||
|
|
if not DATABASE_URL:
|
||
|
|
print("ERROR: DATABASE_URL not set. Cannot backup SQLite — just copy the .db file.")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
backup_dir = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).parent / 'backups'
|
||
|
|
backup_dir.mkdir(parents=True, exist_ok=True)
|
||
|
|
|
||
|
|
timestamp = datetime.utcnow().strftime('%Y%m%d_%H%M%S')
|
||
|
|
filename = backup_dir / f'seafare_backup_{timestamp}.sql'
|
||
|
|
|
||
|
|
print(f"Backing up to {filename}...")
|
||
|
|
|
||
|
|
# pg_dump using DATABASE_URL
|
||
|
|
result = subprocess.run(
|
||
|
|
['pg_dump', DATABASE_URL, '--no-owner', '--no-acl', '-f', str(filename)],
|
||
|
|
capture_output=True, text=True
|
||
|
|
)
|
||
|
|
|
||
|
|
if result.returncode != 0:
|
||
|
|
print(f"ERROR: pg_dump failed: {result.stderr}")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
size_kb = filename.stat().st_size / 1024
|
||
|
|
print(f"Backup complete: {filename} ({size_kb:.1f} KB)")
|
||
|
|
|
||
|
|
# Keep only last 10 backups
|
||
|
|
backups = sorted(backup_dir.glob('seafare_backup_*.sql'), reverse=True)
|
||
|
|
for old in backups[10:]:
|
||
|
|
old.unlink()
|
||
|
|
print(f"Removed old backup: {old.name}")
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
backup()
|