47f7a85510
Die Ampel-Nachruestung deckte 317/337 vorbestehende ruff-Verstoesse im ganzen Repo auf. Aufgeraeumt: - ruff.toml: intentionale Muster als Projekt-Politik ausgenommen (BLE001 blind-except, S110/S112 try-except-pass/continue, PLW1510 subprocess-best-effort, B008 FastAPI- Depends/File-Idiom, EXE001 Shebang, + wenige Stil-Regeln). __init__.py-Re-Exports geschuetzt (F401). - ruff --fix: 128 mechanische (Import-Sortierung, PEP585/604-Annotationen, tote Imports, ueberfluessige noqa) auto-behoben. - 12 echte Reste von Hand: PERF402/102, PLC3002 (Lambda->walrus), ISC004 (String-Concat geklammert), F841/RUF059 (ungenutzte Vars), PIE810 (startswith-Tuple), UP031 (f-string), UP035 (veraltete typing-Imports). Ergebnis: 'ruff check .' = 0, 'compileall' grün. Kein Verhaltenswechsel (nur Stil/Modernisierung). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
93 lines
2.3 KiB
Python
93 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Parse systemd timeout errors for mission-control-2.service from journalctl.
|
|
|
|
Captures lines containing "State 'stop-sigterm' timed out" and appends them
|
|
to ~/logs/mc2-timeout.log with ISO timestamps.
|
|
|
|
Permission errors are handled gracefully.
|
|
|
|
Uses user journal (systemctl --user) to query logs.
|
|
"""
|
|
|
|
import subprocess
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
LOG_DIR = Path.home() / "logs"
|
|
LOG_FILE = LOG_DIR / "mc2-timeout.log"
|
|
SERVICE_NAME = "mission-control-2.service"
|
|
SEARCH_PATTERN = "State 'stop-sigterm' timed out"
|
|
JOURNALCTL_LIMIT = 1000
|
|
|
|
|
|
def ensure_log_dir() -> None:
|
|
"""Create log directory if it doesn't exist."""
|
|
LOG_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
def get_timeout_entries() -> list[str]:
|
|
"""Run journalctl --user and return lines matching the timeout pattern."""
|
|
cmd = [
|
|
"journalctl",
|
|
"--user",
|
|
"-u", SERVICE_NAME,
|
|
"--no-pager",
|
|
"-n", str(JOURNALCTL_LIMIT),
|
|
]
|
|
try:
|
|
result = subprocess.run(
|
|
cmd,
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=30,
|
|
)
|
|
except subprocess.TimeoutExpired:
|
|
print("journalctl timed out")
|
|
return []
|
|
except PermissionError:
|
|
print("Permission denied: journalctl requires access to user logs")
|
|
return []
|
|
|
|
if result.returncode != 0:
|
|
if "Permission denied" in result.stderr:
|
|
print("Permission denied: journalctl requires access to user logs")
|
|
else:
|
|
print(f"journalctl failed: {result.stderr.strip()}")
|
|
return []
|
|
|
|
return [
|
|
line
|
|
for line in result.stdout.splitlines()
|
|
if SEARCH_PATTERN in line
|
|
]
|
|
|
|
|
|
def write_to_log(entries: list[str]) -> int:
|
|
"""Append entries to log file with ISO timestamps. Returns count written."""
|
|
ensure_log_dir()
|
|
|
|
timestamp = datetime.now(timezone.utc).isoformat()
|
|
written = 0
|
|
|
|
with LOG_FILE.open("a", encoding="utf-8") as f:
|
|
for entry in entries:
|
|
f.write(f"[{timestamp}] {entry}\n")
|
|
written += 1
|
|
|
|
return written
|
|
|
|
|
|
def main() -> None:
|
|
entries = get_timeout_entries()
|
|
if not entries:
|
|
print("No timeout entries found.")
|
|
return
|
|
|
|
count = write_to_log(entries)
|
|
print(f"Appended {count} timeout entry/ies to {LOG_FILE}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|