Explorer
/proc/thread-self/root/tmp/create_repair_backup.py
← Zurück ↓ Download
import sqlite3,shutil,os,hashlib,json,subprocess
from pathlib import Path
from datetime import datetime,timezone
stamp=datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%SZ')
root=Path('/home/hermes')/f'Wissenspipeline-Repair-Phase-1-Backup-{stamp}'
root.mkdir(parents=True,exist_ok=False)
DB=Path('/opt/struktur/youtube-research/knowledge.db')
# Consistent SQLite online backup, read-only source connection.
src=sqlite3.connect(f'file:{DB}?mode=ro',uri=True)
dst=sqlite3.connect(root/'knowledge.db')
src.backup(dst); dst.close(); src.close()
# Capture sidecar state without relying on sidecar copy for consistency.
side={}
for p in [DB,Path(str(DB)+'-wal'),Path(str(DB)+'-shm')]:
 try: side[str(p)]={'exists':p.exists(),'size':p.stat().st_size if p.exists() else None,'mtime':p.stat().st_mtime if p.exists() else None}
 except Exception as e: side[str(p)]={'error':str(e)}
(root/'sqlite-sidecars.json').write_text(json.dumps(side,indent=2))
# Read-only state snapshots.
shutil.copy2('/tmp/repair_preflight.json',root/'preflight.json')
# Queue, registry, source versions, FK report from backup copy.
c=sqlite3.connect(root/'knowledge.db'); c.row_factory=sqlite3.Row
for name,sql in {
 'queue-snapshot.json':'select * from graphiti_import_queue order by id',
 'registry-snapshot.json':'select * from source_processing_registry order by id',
 'source-versions-snapshot.json':'select * from source_versions order by version_id',
 'fk-check.json':'pragma foreign_key_check'
}.items(): (root/name).write_text(json.dumps([dict(x) for x in c.execute(sql).fetchall()],ensure_ascii=False,indent=2,default=str))
c.close()
# Relevant unit/code snapshots; never copy credentials.
files=['/etc/systemd/system/aa049-queue.service','/etc/systemd/system/aa049-queue.timer','/opt/struktur/youtube-research/e2e_worker.py','/opt/struktur/youtube-research/app.py','/opt/struktur/youtube-research/db.py','/opt/struktur/graphiti/youtube_graphiti_queue.py','/opt/struktur/graphiti/service/main.py','/opt/struktur/graphiti/scope_policy_checker.py','/opt/struktur/reports/aa049-worker-events.jsonl']
manifest=[]
for s in files:
 p=Path(s); rec={'source':s}
 try:
  if p.is_file():
   dest=root/'files'/s.lstrip('/'); dest.parent.mkdir(parents=True,exist_ok=True); shutil.copy2(p,dest); rec.update({'copied':True,'backup':str(dest),'size':p.stat().st_size})
  else: rec['copied']=False
 except Exception as e: rec.update({'copied':False,'error':str(e)})
 manifest.append(rec)
(root/'file-manifest.json').write_text(json.dumps(manifest,ensure_ascii=False,indent=2))
# hashes of backup files
hashes=[]
for p in root.rglob('*'):
 if p.is_file():
  h=hashlib.sha256();
  with p.open('rb') as f:
   for b in iter(lambda:f.read(1024*1024),b''):h.update(b)
  hashes.append({'path':str(p),'size':p.stat().st_size,'sha256':h.hexdigest()})
(root/'SHA256SUMS.json').write_text(json.dumps(hashes,ensure_ascii=False,indent=2))
print(json.dumps({'backup_path':str(root),'timestamp':stamp,'db_backup_size':(root/'knowledge.db').stat().st_size,'files':manifest,'hash_count':len(hashes)},ensure_ascii=False,indent=2))