vdi-cloud/terminal/kiosk-shell/scripts/vdi-observer-pstore

38 lines
1.6 KiB
Python

#!/usr/bin/env python3
"""Root-owned, read-only pstore snapshot; never clears kernel/archive records."""
from datetime import datetime
import grp
import json
import os
from pathlib import Path
import tempfile
folder = Path('/var/lib/vdi-observer')
folder.mkdir(mode=0o750, exist_ok=True)
if folder.is_symlink() or folder.stat().st_uid != 0:
raise RuntimeError('Unsafe pstore snapshot directory')
gid = grp.getgrnam('systemd-journal').gr_gid
os.chown(folder, 0, gid); os.chmod(folder, 0o750)
data = {'captured_at': datetime.now().astimezone().isoformat(),
'boot_id': Path('/proc/sys/kernel/random/boot_id').read_text().strip(), 'sources': {}}
for root in (Path('/sys/fs/pstore'), Path('/var/lib/systemd/pstore')):
try:
entries = {}
for p in sorted(root.iterdir())[:8]:
if p.is_symlink() or not p.is_file(): continue
with p.open('rb') as stream: raw = stream.read(32768)
entries[p.name] = {'mtime': p.stat().st_mtime, 'text': raw.decode(errors='replace'), 'truncated': p.stat().st_size > 32768}
data['sources'][str(root)] = entries
except OSError as e: data['sources'][str(root)] = {'error': str(e)}
name = None
try:
with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', dir=folder, delete=False) as f:
name = f.name; os.fchown(f.fileno(), 0, gid); os.fchmod(f.fileno(), 0o640)
json.dump(data, f, ensure_ascii=False); f.flush(); os.fsync(f.fileno())
os.replace(name, folder/'pstore.json'); name = None
fd = os.open(folder, os.O_RDONLY | os.O_DIRECTORY)
try: os.fsync(fd)
finally: os.close(fd)
finally:
if name: os.unlink(name)