#!/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 <.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