Kernel Panic decoderen vanuit een QR-code foto
Gebruik
Het script kan als volgt worden uitgevoerd:
./decode-kernel-panic.py screenshot.png -o panic.log
De Code
#!/usr/bin/env python3
"""
Scan een Linux panic QR-code met ZXingReader en decomprimeer het crashlogboek.
./decode-kernel-panic.py screenshot.png -o panic.log
"""
import argparse
import json
from pathlib import Path
import subprocess
import sys
from urllib.parse import parse_qs, urlsplit
import zlib
def decode_panic_url(url):
"""Decodeer de z-parameter van de kernel: 17 decimale cijfers per 7 little-endian bytes.
Format referentie: https://github.com/kdj0c/panic_report
"""
parts = urlsplit(url)
parameters = parse_qs(parts.query, keep_blank_values=True)
if "z" not in parameters:
parameters = parse_qs(parts.fragment.lstrip("?"), keep_blank_values=True)
if "z" not in parameters:
raise ValueError("QR-code URL bevat geen gecomprimeerde panic-data (z-parameter)")
if len(parameters["z"]) != 1:
raise ValueError("QR-code URL bevat meerdere z-parameters")
digits = parameters["z"][0]
if not digits or not digits.isascii() or not digits.isdecimal():
raise ValueError("panic-data moet uitsluitend decimale cijfers bevatten")
# Een laatste, gedeeltelijke groep gebruikt minder cijfers en bytes.
byte_counts = {3: 1, 5: 2, 8: 3, 10: 4, 13: 5, 15: 6, 17: 7}
compressed = bytearray()
for offset in range(0, len(digits), 17):
chunk = digits[offset:offset + 17]
if len(chunk) not in byte_counts:
raise ValueError("ongeldige lengte van gecodeerde panic-data")
try:
compressed.extend(int(chunk).to_bytes(byte_counts[len(chunk)], "little"))
except OverflowError as exc:
raise ValueError("gecodeerde panic-data bevat een chunk buiten bereik") from exc
return zlib.decompress(compressed)
def scan_image(image):
if not image.is_file():
raise ValueError(f"afbeelding bestaat niet of is geen bestand: {image}")
try:
result = subprocess.run(
["ZXingReader", "-formats", "QRCode", "-json", str(image.resolve())],
capture_output=True,
text=True,
)
except FileNotFoundError as exc:
raise ValueError("ZXingReader is vereist; installeer dit en voeg het toe aan PATH") from exc
if result.returncode != 0:
detail = result.stderr.strip() or "geen leesbare QR-code gevonden"
raise ValueError(f"ZXingReader is mislukt: {detail}")
if not result.stdout.strip():
raise ValueError("geen leesbare QR-code gevonden")
try:
qr = json.loads(result.stdout)
except json.JSONDecodeError as exc:
raise ValueError("verwacht één QR-code in de JSON-output van ZXingReader") from exc
if not isinstance(qr, dict) or not isinstance(qr.get("Text"), str):
raise ValueError("ZXingReader retourneerde geen QR-code tekst")
return qr["Text"]
def main():
parser = argparse.ArgumentParser(
description="Scan een Linux panic screenshot met ZXingReader en decomprimeer het logboek.",
epilog="Vereist Python 3 en ZXingReader. Het decoderen vindt lokaal plaats zonder netwerktoegang.",
)
parser.add_argument("image", type=Path, help="screenshot of foto met de panic QR-code")
parser.add_argument("-o", "--output", type=Path, help="schrijf het logboek naar een bestand in plaats van stdout")
args = parser.parse_args()
try:
if args.output and args.output.resolve() == args.image.resolve():
raise ValueError("output moet verschillen van de invoer-afbeelding")
log = decode_panic_url(scan_image(args.image))
if args.output:
args.output.write_bytes(log)
else:
sys.stdout.buffer.write(log)
except BrokenPipeError:
# Sta commando's toe zoals `decode-kernel-panic screenshot.png | head`.
import os
os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno())
return 0
except (OSError, ValueError, zlib.error) as exc:
print(f"{parser.prog}: {exc}", file=sys.stderr)
return 1
return 0
if __name__ == "__main__":
sys.exit(main())
Vereisten en Details
- Softwarevereisten: Python 3 en ZXingReader.
- Privacy: Het decoderen wordt lokaal uitgevoerd; er is geen netwerktoegang nodig.
- Functionaliteit:
- Het script extraheert de tekst uit een QR-code in een afbeelding.
- Het decodeert de
z-parameter uit de URL, waarbij 17 decimale cijfers worden omgezet naar 7 little-endian bytes. - De data wordt vervolgens gedecomprimeerd met behulp van
zlib.
Groetjes,