
Decode kernel panic from QR Code photo
Instantly share code, notes, and snippets.
以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。
Instantly share code, notes, and snippets.
Show Gist options
Download ZIP
Star
0 (0)
You must be signed in to star a gist
Fork
0 (0)
You must be signed in to fork a gist
Embed
Select an option
Embed Embed this gist in your website.
Share Copy sharable link for this gist.
Clone via HTTPS Clone using the web URL.
No results found
Learn more about clone URLs
Clone this repository at <script src="https://gist.github.com/skorotkiewicz/c59e591c26661cb52b06afc42d8ac546.js"></script>
Save skorotkiewicz/c59e591c26661cb52b06afc42d8ac546 to your computer and use it in GitHub Desktop.
Code
Revisions 3
Embed
Select an option
Embed Embed this gist in your website.
Share Copy sharable link for this gist.
Clone via HTTPS Clone using the web URL.
No results found
Learn more about clone URLs
Clone this repository at <script src="https://gist.github.com/skorotkiewicz/c59e591c26661cb52b06afc42d8ac546.js"></script>
Save skorotkiewicz/c59e591c26661cb52b06afc42d8ac546 to your computer and use it in GitHub Desktop.
Download ZIP
decode kernel panic from QR Code photo
Raw
decode-kernel-panic.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Show hidden characters
#!/usr/bin/env python3
"""
Scan a Linux panic QR code with ZXingReader and decompress its crash log.
./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):
"""Decode the kernel's z parameter: 17 decimal digits per 7 little-endian bytes.
Format reference: 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 has no compressed panic data (z parameter)")
if len(parameters["z"]) != 1:
raise ValueError("QR code URL has multiple z parameters")
digits = parameters["z"][0]
if not digits or not digits.isascii() or not digits.isdecimal():
raise ValueError("panic data must contain only decimal digits")
A final, partial group uses fewer digits and 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("invalid length of encoded panic data")
try:
compressed.extend(int(chunk).to_bytes(byte_counts[len(chunk)], "little"))
except OverflowError as exc:
raise ValueError("encoded panic data contains an out-of-range chunk") from exc
return zlib.decompress(compressed)
def scan_image(image):
if not image.is_file():
raise ValueError(f"image does not exist or is not a file: {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 required; install it and put it on PATH") from exc
if result.returncode != 0:
detail = result.stderr.strip() or "no readable QR code found"
raise ValueError(f"ZXingReader failed: {detail}")
if not result.stdout.strip():
raise ValueError("no readable QR code found")
try:
qr = json.loads(result.stdout)
except json.JSONDecodeError as exc:
raise ValueError("expected one QR code in ZXingReader's JSON output") from exc
if not isinstance(qr, dict) or not isinstance(qr.get("Text"), str):
raise ValueError("ZXingReader returned no QR code text")
return qr["Text"]
def main():
parser = argparse.ArgumentParser(
description="Scan a Linux panic screenshot with ZXingReader and decompress its log.",
epilog="Requires Python 3 and ZXingReader. Decoding runs locally without network access.",
)
parser.add_argument("image", type=Path, help="screenshot or photo containing the panic QR code")
parser.add_argument("-o", "--output", type=Path, help="write the log to a file instead of stdout")
args = parser.parse_args()
try:
if args.output and args.output.resolve() == args.image.resolve():
raise ValueError("output must differ from the input image")
log = decode_panic_url(scan_image(args.image))
if args.output:
args.output.write_bytes(log)
else:
sys.stdout.buffer.write(log)
except BrokenPipeError:
Allow commands such as 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())
skorotkiewicz
commented
Oct 30, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
Copy link
Copy Markdown
Author
./decode-kernel-panic.py screenshot.png -o panic.log
There was an error while loading. Please reload this page.
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。