#!/usr/bin/env python3 import os import sqlite3 from pathlib import Path source_path = Path("/data/main.db") backup_dir = Path("/data/backup") temporary_path = backup_dir / "main.db.tmp" backup_path = backup_dir / "main.db" os.umask(0o077) backup_dir.mkdir(mode=0o700, parents=True, exist_ok=True) temporary_path.unlink(missing_ok=True) try: # Read-only mode prevents silently creating an empty source database. source = sqlite3.connect( f"{source_path.as_uri()}?mode=ro", uri=True, timeout=60, ) destination = sqlite3.connect(temporary_path) try: source.backup(destination, pages=256, sleep=0.1) result = destination.execute("PRAGMA integrity_check").fetchall() if result != [("ok",)]: raise RuntimeError(f"SQLite integrity check failed: {result}") finally: destination.close() source.close() # Only publish a fully written, verified snapshot. os.replace(temporary_path, backup_path) print(f"SQLite backup ready: {backup_path}", flush=True) except Exception: temporary_path.unlink(missing_ok=True) raise