#!/bin/bash set -e PATH=/sbin:/bin:/usr/sbin:/usr/bin KERNEL_VER="7.0.9+deb14-amd64" MODULES_DIR="/lib/modules/${KERNEL_VER}" add_0version() { echo '** Version:' >&3 cat /proc/version >&3 echo >&3 if [ "$(uname -r)" != "$KERNEL_VER" ]; then echo '########################################################################' >&3 echo '########################################################################' >&3 echo 'Running kernel does not match package!' >&3 echo '########################################################################' >&3 echo '########################################################################' >&3 echo >&3 fi } add_0version add_1cmdline() { echo '** Command line:' >&3 cat /proc/cmdline >&3 echo >&3 } add_1cmdline _check_1tainted() { if [ $(($tainted & 1<<$1)) -ne 0 ]; then result_short="$result_short$2" result_long="$result_long * $3\n" fi } add_1tainted() { tainted=$(cat /proc/sys/kernel/tainted) if [ "$tainted" -gt 0 ]; then local result_short result_long # Use debian/bin/update-bug-taint-list to update this _check_1tainted 0 P 'proprietary module was loaded' _check_1tainted 1 F 'module was force loaded' _check_1tainted 2 S 'kernel running on an out of specification system' _check_1tainted 3 R 'module was force unloaded' _check_1tainted 4 M 'processor reported a Machine Check Exception (MCE)' _check_1tainted 5 B 'bad page referenced or some unexpected page flags' _check_1tainted 6 U 'taint requested by userspace application' _check_1tainted 7 D 'kernel died recently, i.e. there was an OOPS or BUG' _check_1tainted 8 A 'ACPI table overridden by user' _check_1tainted 9 W 'kernel issued warning' _check_1tainted 10 C 'staging driver was loaded' _check_1tainted 11 I 'workaround for bug in platform firmware applied' _check_1tainted 12 O 'externally-built ("out-of-tree") module was loaded' _check_1tainted 13 E 'unsigned module was loaded' _check_1tainted 14 L 'soft lockup occurred' _check_1tainted 15 K 'kernel has been live patched' _check_1tainted 16 X 'auxiliary taint, defined for and used by distros' _check_1tainted 17 T 'kernel was built with the struct randomization plugin' _check_1tainted 18 N 'an in-kernel test has been run' echo "** Tainted: $result_short ($tainted)" >&3 printf "$result_long" >&3 else echo '** Not tainted' >&3 fi echo >&3 } add_1tainted add_dmesg() { local got_log= echo '** Kernel log:' >&3 if journalctl --system --dmesg --boot=0 --lines=100 --no-pager >&3 2>/dev/null; then got_log=y elif [ "$(cat /proc/sys/kernel/dmesg_restrict)" = 0 ]; then dmesg > >(tail -n 100 >&3) && got_log=y elif command -v sudo >/dev/null; then yesno "Use sudo to read the kernel log? " yep if [ "$REPLY" = yep ]; then sudo dmesg > >(tail -n 100 >&3) && got_log=y fi fi test "$got_log" || echo 'Unable to read kernel log; any relevant messages should be attached' >&3 echo >&3 } add_dmesg grep_model() { case "$(uname -m)" in alpha) grep -E '^(system (type|variation|revision)|platform string)\b' /proc/cpuinfo ;; arm*) grep -E '^(Processor|Hardware|Revision)\b' /proc/cpuinfo ;; x86_64) local found= for name in {sys,product,chassis,bios,board}_{vendor,name,version}; do if [ -f /sys/class/dmi/id/$name ]; then echo -n "$name: " cat /sys/class/dmi/id/$name found=y fi done test -n "$found" ;; mips|mips64) grep -E '^(system type|cpu model)\b' /proc/cpuinfo ;; parisc|parisc64) grep -E '^(model|[hs]version)\b' /proc/cpuinfo ;; ppc|ppc64|ppc64le) grep -E -i '^(board|machine|model|motherboard|platform|revision|vendor)\b' /proc/cpuinfo ;; s390|s390x) grep -E '^processor\b' /proc/cpuinfo ;; sparc|sparc64) grep -E '^(cpu|fpu|pmu|prom|type)\b' /proc/cpuinfo ;; sh4|sh4a) grep -E '^(machine|cpu)\b' /proc/cpuinfo ;; *) false ;; esac # Device Tree model if [ -r /proc/device-tree/model ]; then echo "Device Tree model:" $(cat /proc/device-tree/model) fi } add_model() { local found= echo '** Model information' >&3 grep_model >&3 2>/dev/null || echo "not available" >&3 echo >&3 } add_model add_modprobe() { echo '** Configuration for modprobe:' >&3 modprobe -c | sed -r -e '/^(alias|softdep|#|$)/d' | LC_ALL=C sort >&3 echo >&3 } add_modprobe add_modules() { echo '** Loaded modules:' >&3 # List modules along with any taint flags. # Sort first by taint status, so tainting modules are listed at front cut -d' ' -f1,7 /proc/modules | LC_ALL=C sort -k2br,2 -k1b,1 | sed 's/ //' >&3 echo >&3 } add_modules add_modules_extern() { echo '** Out of tree modules:' >&3 if [[ -e $MODULES_DIR/modules.order ]]; then find "$MODULES_DIR" -name "*.ko" -o -name "*.ko.*" -printf '%P\n' | sed -re 's/\.(xz|zstd)$//' | grep -vxFf "$MODULES_DIR"/modules.order >&3 || echo 'None found' >&3 else echo 'Unable to check' >&3 fi echo >&3 } add_modules_extern _list_etc_network_interfaces() { local file for file in /etc/network/interfaces /etc/network/interfaces.d/*; do if ! [ -f "$file" ]; then continue fi case "${file##*/}" in *[^-a-zA-Z0-9_]*) continue ;; esac echo "$file" done } _add_etc_network_interfaces() { local file test -f /etc/network/interfaces || return 0 echo '** Network interface configuration:' >&3 while read file; do if ! [ -r "$file" ]; then echo "*** $file: unreadable" >&3 echo >&3 continue fi echo "*** $file:" >&3 # Hide passwords/keys awk '$1 ~ /key|pass|^wpa-(anonymous|identity|phase|pin|private|psk)/ { gsub(".", "*", $2); } $1 == "ethtool-wol" { gsub(".", "*", $3); } !/^[[:space:]]*\#/ { print; } ' <"$file" >&3 echo >&3 done < <(_list_etc_network_interfaces) } add_network() { yesno "Include network configuration and status from this computer? " nop test $REPLY = yep || return 0 _add_etc_network_interfaces echo '** Network status:' >&3 if command -v ip >/dev/null; then echo '*** IP interfaces and addresses:' >&3 ip address show >&3 echo >&3 fi echo '*** Device statistics:' >&3 cat /proc/net/dev >&3 echo >&3 if command -v netstat >/dev/null; then echo '*** Protocol statistics:' >&3 netstat -s >&3 || true echo >&3 fi echo >&3 } add_network add_pci() { echo '** PCI devices:' >&3 lspci -nnkPPD >&3 2>/dev/null || echo 'not available' >&3 echo >&3 } add_pci _add_pstore_log() { if [ $# -le 3 ]; then return fi local backend="$1" local event="$2" local date="$3" yesno "Include log of $event at $(date -d @$date +%c) stored by $backend?" yep if [ $REPLY != yep ]; then return fi echo >&3 echo "*** Log of $event at $(date -d @$date -Iseconds) from $backend" >&3 shift 3 for file in "$@"; do tail -n +2 "$file" | sed 's/^<.>//' >&3 done } add_pstore() { local backend local i local j local file local date local head local event local log_files if ! mountpoint -q /sys/fs/pstore; then return 0 fi set -- /sys/fs/pstore/dmesg-*-1 backend=${1#*/dmesg-} backend=${backend%-1} if [ "$backend" = '*' ]; then return 0 fi i=1 while [ -f /sys/fs/pstore/dmesg-$backend-$i ]; do file=/sys/fs/pstore/dmesg-$backend-$i head="$(head -1 "$file")" # Is this the first part of a log? if [ "x${head% Part1}" != "x$head" ]; then # Flush previous log, if any _add_pstore_log "$backend" "$event" "$date" $log_files event="${head% Part1}" date=$(stat -c %Y $file) log_files= j=1 fi if [ "x$head" = "x$event Part$j" ]; then # Each part is prepended to the list, because they're numbered # backward in log history log_files="$file $log_files" j=$((j + 1)) fi i=$((i + 1)) done # Flush last log, if any _add_pstore_log "$backend" "$event" "$date" $log_files } add_pstore add_usb() { echo '** USB devices:' >&3 lsusb -tv >&3 2>/dev/null || echo 'not available' >&3 echo >&3 } add_usb