Files
ArchyHCL/site/gather-hardware-info.sh
T
ssmithxandClaude Sonnet 5 5df5b50dca
Deploy / deploy (push) Successful in 4s
Add gather-hardware-info.sh — auto-detects most report fields
Reads /proc, /sys, and common CLI tools (lscpu, lsblk, lspci, lsusb) to
print a YAML block matching data/schema.json: device model (DMI on x86,
/proc/device-tree/model on ARM SBCs), form factor (best-effort — battery
presence, DMI chassis type, device-tree presence), CPU, RAM, root storage
type/size, WiFi chip (PCI, then USB, then falls back to driver name rather
than guessing wrong), ethernet. Fields it can't detect (archy_version,
install_method, status) are left as clearly-marked TODOs rather than
guessed. Local-only — no network calls, changes nothing.

Tested for real on this box (a QEMU VM): correctly identified it as a VM,
correctly fell back to "other" with a TODO for form_factor rather than
guessing, output validated as parseable YAML. Passes shellcheck clean.

Linked from the homepage, report.html, and CONTRIBUTING.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 02:49:02 +00:00

143 lines
5.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# gather-hardware-info.sh — collects the fields ArchyHCL's report form asks
# for and prints a YAML block matching data/schema.json, ready to paste into
# https://hcl.archipelago-foundation.org/report.html or a PR.
#
# Read before you run, like any script from the internet:
# https://source.archipelago-foundation.org/ssmithx/ArchyHCL/src/branch/main/site/gather-hardware-info.sh
#
# Local-only: reads /proc, /sys, and a few common CLI tools. Makes no
# network calls and changes nothing on the system. Some fields (WiFi chip
# on non-PCI hardware, device model on some boards) can't be detected
# reliably everywhere — those are left as TODO rather than guessed wrong.
#
# Usage: ./gather-hardware-info.sh (or: bash gather-hardware-info.sh)
set -uo pipefail
have() { command -v "$1" >/dev/null 2>&1; }
# --- device model ---
device_model="TODO — e.g. \"Lenovo ThinkPad T430\""
if [ -r /proc/device-tree/model ]; then
# Raspberry Pi and most other ARM SBCs expose a clean model string here,
# null-terminated.
device_model="$(tr -d '\0' < /proc/device-tree/model)"
elif [ -r /sys/class/dmi/id/sys_vendor ] && [ -r /sys/class/dmi/id/product_name ]; then
vendor="$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null)"
product="$(cat /sys/class/dmi/id/product_name 2>/dev/null)"
if [ -n "$vendor" ] && [ -n "$product" ]; then
device_model="$vendor $product"
fi
fi
# --- form factor (best-effort guess — double-check this one) ---
form_factor="other # TODO: couldn't guess confidently, pick laptop|desktop|mini-pc|sbc|server|other"
if [ -r /proc/device-tree/model ]; then
form_factor="sbc"
elif ls /sys/class/power_supply/BAT* >/dev/null 2>&1; then
form_factor="laptop"
elif [ -r /sys/class/dmi/id/chassis_type ]; then
case "$(cat /sys/class/dmi/id/chassis_type 2>/dev/null)" in
8|9|10|14) form_factor="laptop" ;; # Portable/Laptop/Notebook/Sub-Notebook
3|4|6|7) form_factor="desktop" ;; # Desktop/Low Profile Desktop/Mini Tower/Tower
35|36) form_factor="mini-pc" ;; # Small Form Factor variants some vendors use
23) form_factor="server" ;; # Rack Mount Chassis
esac
fi
# --- CPU ---
if have lscpu; then
cpu="$(lscpu | awk -F: '/^Model name/ {print $2; exit}' | sed 's/^ *//')"
fi
if [ -z "${cpu:-}" ]; then
cpu="$(awk -F: '/^model name/ {print $2; exit}' /proc/cpuinfo | sed 's/^ *//')"
fi
if [ -z "${cpu:-}" ]; then
# ARM boards often don't set "model name" — fall back to the SoC line.
cpu="$(awk -F: '/^Hardware|^Model/ {print $2; exit}' /proc/cpuinfo | sed 's/^ *//')"
fi
[ -z "${cpu:-}" ] && cpu="TODO — could not detect, check \`lscpu\` or \`cat /proc/cpuinfo\`"
# --- RAM (rounded up to the nearest whole GB) ---
ram_kb="$(awk '/MemTotal/ {print $2}' /proc/meminfo)"
ram_gb=$(( (ram_kb + 1048575) / 1048576 ))
# --- root filesystem storage: type + size ---
storage_type="TODO"
storage_size_gb="TODO"
if have lsblk && have findmnt; then
root_src="$(findmnt -no SOURCE / 2>/dev/null || true)"
root_dev="$(lsblk -no PKNAME "$root_src" 2>/dev/null || true)"
[ -z "$root_dev" ] && root_dev="$(basename "${root_src:-}" 2>/dev/null | sed -E 's/p?[0-9]+$//')"
if [ -n "$root_dev" ] && [ -b "/dev/$root_dev" ]; then
size_bytes="$(lsblk -bno SIZE "/dev/$root_dev" 2>/dev/null | head -1)"
if [ -n "$size_bytes" ]; then
storage_size_gb=$(( size_bytes / 1073741824 ))
fi
case "$root_dev" in
nvme*) storage_type="nvme" ;;
mmcblk*) storage_type="emmc" ;;
*)
if [ -r "/sys/block/$root_dev/queue/rotational" ]; then
if [ "$(cat "/sys/block/$root_dev/queue/rotational")" = "0" ]; then
storage_type="ssd"
else
storage_type="hdd"
fi
fi
;;
esac
fi
fi
# --- WiFi chip: try PCI, then USB, then fall back to the driver name ---
wifi_chip="none"
wifi_iface=""
for w in /sys/class/net/*/wireless; do
[ -d "$w" ] || continue
wifi_iface="$(basename "$(dirname "$w")")"
break
done
if [ -n "$wifi_iface" ]; then
if have lspci; then
wifi_chip="$(lspci | grep -iE 'network controller|wireless' | head -1 | sed -E 's/^[0-9a-f:.]+ [^:]+: //')"
fi
if [ -z "$wifi_chip" ] && have lsusb; then
wifi_chip="$(lsusb | grep -iE 'wireless|wifi|802\.11' | head -1 | sed -E 's/^Bus [0-9]+ Device [0-9]+: ID [0-9a-f]{4}:[0-9a-f]{4} //')"
fi
if [ -z "$wifi_chip" ] && [ -r "/sys/class/net/$wifi_iface/device/uevent" ]; then
driver="$(awk -F= '/^DRIVER=/ {print $2}' "/sys/class/net/$wifi_iface/device/uevent")"
[ -n "$driver" ] && wifi_chip="driver: $driver (chip model not auto-detected — check \`lsusb\`/\`lspci\` by hand)"
fi
[ -z "$wifi_chip" ] && wifi_chip="TODO — wireless interface $wifi_iface found but chip not identified"
fi
# --- Ethernet chip (best-effort) ---
ethernet=""
if have lspci; then
ethernet="$(lspci | grep -i 'ethernet controller' | head -1 | sed -E 's/^[0-9a-f:.]+ [^:]+: //')"
fi
today="$(date +%F 2>/dev/null || echo "TODO")"
cat <<YAML
# Auto-gathered by gather-hardware-info.sh — check every field, especially
# any marked TODO, then paste this into:
# https://hcl.archipelago-foundation.org/report.html (fill the form instead — easiest)
# or add it directly as data/reports/<slug>.yml in a PR — see CONTRIBUTING.md
device_model: "$device_model"
form_factor: $form_factor
cpu: "$cpu"
ram_gb: $ram_gb
storage:
type: $storage_type
size_gb: $storage_size_gb
wifi_chip: "$wifi_chip"
$( [ -n "$ethernet" ] && echo "ethernet: \"$ethernet\"" )
archy_version: "TODO — e.g. 1.8.10-alpha"
install_method: TODO # usb-iso | netboot | existing-os-script | other
status: TODO # working | partial | broken
tested_date: "$today"
YAML