From 5280e1c9eb97744779eaeed19cb74c2525ea3bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Ara=C3=BAjo?= Date: Tue, 30 Jun 2026 13:44:28 +0000 Subject: [PATCH] Add a bug report tool that collects essential info automatically Adds a `kde-linux-collect-logs` command-line tool that collects system diagnostics into a single timestamped `.tar.zst` archive for attaching to bug reports. It gathers a system summary, a full `inxi -Faz` dump, graphics info (`drm_info`, `kscreen-doctor -o`), the environment, `/etc/fstab`, `dmesg`, boot journals, and a few KDE-specific extras, writing each to its own file and skipping missing tools gracefully. Refuses to run inside a container, and `inxi -z` auto-filters MACs and serials. Also adds `inxi` to the CLI package set, since it forms the basis of the report. Resolves #547 --- mkosi.conf.d/80-packages-cli.conf | 1 + mkosi.extra/usr/bin/collect-logs | 113 ++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100755 mkosi.extra/usr/bin/collect-logs diff --git a/mkosi.conf.d/80-packages-cli.conf b/mkosi.conf.d/80-packages-cli.conf index 95100ed..0f31d6a 100644 --- a/mkosi.conf.d/80-packages-cli.conf +++ b/mkosi.conf.d/80-packages-cli.conf @@ -50,6 +50,7 @@ Packages= git-lfs # Git extension needed for versioning large files gping # Opinionated fancy ping htop # Opinionated fancy top + inxi # Comprehensive system information iotop # Opinionated fancy top for disks jq # JSON processor libratbag # Inspect and modify configurable mice diff --git a/mkosi.extra/usr/bin/collect-logs b/mkosi.extra/usr/bin/collect-logs new file mode 100755 index 0000000..461bd5a --- /dev/null +++ b/mkosi.extra/usr/bin/collect-logs @@ -0,0 +1,113 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL +# SPDX-FileCopyrightText: 2026 Felipe Araújo + +# Collect system diagnostics into a .tar.zst archive for bug reports. + +set -eu + +if systemd-detect-virt --container --quiet; then + echo "Results won’t be accurate when running inside a container; exiting." >&2 + exit 1 +fi + +report_name="kde-linux-logs-$(date +%Y%m%d-%H%M%S)" +work_dir="$(mktemp -d)" +report_dir="${work_dir}/${report_name}" +mkdir -p "${report_dir}" +trap 'rm -rf "${work_dir}"' EXIT + +# collect [args...] +collect() { + out="${report_dir}/$1" + shift + cmd="$1" + if [ "${cmd}" = run0 ] || [ "${cmd}" = sudo ] || [ "${cmd}" = pkexec ]; then + cmd="$2" + fi + echo "Collecting ${cmd}…" + if ! command -v "$1" >/dev/null 2>&1; then + echo "command “$1“ not found; skipped." > "${out}" + return 0 + fi + { + echo "# $*" + echo + "$@" 2>&1 + } > "${out}" || echo "(command exited with an error)" >> "${out}" +} + +# Escape sed metacharacters in $1. +sed_escape() { + printf '%s\n' "$1" | sed 's/[][\\.^$*|]/\\&/g' +} + +# Best-effort redaction of common identifiers from every collected file. +redact() { + echo "Sanitizing logs…" + + # IPv4, MAC, and e-mail addresses. + prog=' +s/\b\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\b//g +s/\b\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}\b//g +s/[A-Za-z0-9._%+-]\{1,\}@[A-Za-z0-9.-]\{1,\}\.[A-Za-z]\{2,\}//g' + + host="$(hostname 2>/dev/null || uname -n)" + if [ -n "${host}" ]; then + prog="${prog} +s|$(sed_escape "${host}")||g" + fi + + user="$(id -un 2>/dev/null || true)" + if [ -n "${user}" ] && [ "${user}" != root ]; then + esc_user="$(sed_escape "${user}")" + prog="${prog} +s|/home/${esc_user}|/home/|g +s|${esc_user}||g" + fi + + find "${report_dir}" -type f -exec sed -i "${prog}" {} + +} + +{ + echo "Date: $(date)" + echo "Uptime: $(uptime)" + echo "Kernel: $(uname -a)" + echo "Cmdline: $(cat /proc/cmdline)" +} > "${report_dir}/summary.txt" + +collect inxi.txt inxi -Faz +collect drm-info.txt drm_info +collect kscreen.txt kscreen-doctor -o +# kscreen-doctor forces colored output; strip ANSI escape codes for readability. +sed -i "s/$(printf '\033')\[[0-9;]*m//g" "${report_dir}/kscreen.txt" + +env > "${report_dir}/env.txt" +if [ -r /etc/fstab ]; then + cp /etc/fstab "${report_dir}/fstab.txt" +fi + +collect dmesg.txt run0 dmesg +journalctl -b 0 -p 4 --no-pager > "${report_dir}/journal-current-boot.txt" 2>&1 || true +journalctl -b -1 -p 4 --no-pager > "${report_dir}/journal-previous-boot.txt" 2>&1 || true + +if command -v brew >/dev/null 2>&1; then + collect homebrew-packages.txt brew list --versions +fi + +collect kinfo.txt kinfo + +redact + +output="${PWD}/${report_name}.tar.zst" +tar -C "${work_dir}" -c "${report_name}" | zstd -q -T0 -o "${output}" + +echo +echo "Log bundle saved to:" +echo " ${output}" +echo +echo "Please review its contents before sharing; the logs went through" +echo "sanitization, but some personal information may remain." +echo +echo "You can attach this bundle to a bug report at:" +echo " https://invent.kde.org/kde-linux/kde-linux/-/work_items"