393 lines
15 KiB
Bash
Executable file
393 lines
15 KiB
Bash
Executable file
#!/bin/sh
|
|
# Collect a local hardware report for Clawdie live-USB support and future
|
|
# custom ISO builds. This command never uploads unless explicitly requested.
|
|
|
|
set -u
|
|
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
export PATH
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: hw-report [--upload-public-probe] [--no-smart]
|
|
|
|
Collect a local hardware diagnostics bundle under /home/clawdie/hw-reports
|
|
when that home directory exists, otherwise under $HOME/hw-reports.
|
|
|
|
Options:
|
|
--upload-public-probe Also run hw-probe -all -upload. This submits an
|
|
anonymous public report to bsd-hardware.info.
|
|
--no-smart Skip smartctl disk probes.
|
|
-h, --help Show this help.
|
|
|
|
Recommended live-USB invocation:
|
|
mdo -u root hw-report
|
|
EOF
|
|
}
|
|
|
|
_upload_public_probe="NO"
|
|
_run_smart="YES"
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--upload-public-probe)
|
|
_upload_public_probe="YES"
|
|
;;
|
|
--no-smart)
|
|
_run_smart="NO"
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "ERROR: unknown option: $1" >&2
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "WARNING: not running as root; some hardware data will be incomplete." >&2
|
|
echo "Recommended: mdo -u root hw-report" >&2
|
|
fi
|
|
|
|
_stamp="$(date -u '+%Y%m%dT%H%M%SZ')"
|
|
_host="$(hostname 2>/dev/null || echo clawdie-live)"
|
|
_report_name="hw-report-${_host}-${_stamp}"
|
|
|
|
if [ -d /home/clawdie ]; then
|
|
_base="${CLAWDIE_HW_REPORT_DIR:-/home/clawdie/hw-reports}"
|
|
else
|
|
_base="${CLAWDIE_HW_REPORT_DIR:-${HOME:-/root}/hw-reports}"
|
|
fi
|
|
_report_dir="${_base}/${_report_name}"
|
|
_raw_dir="${_report_dir}/raw"
|
|
_logs_dir="${_report_dir}/logs"
|
|
|
|
mkdir -p "${_raw_dir}" "${_logs_dir}"
|
|
|
|
_log="${_report_dir}/collection.log"
|
|
: > "${_log}"
|
|
|
|
note() {
|
|
printf '%s %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$*" | tee -a "${_log}"
|
|
}
|
|
|
|
have() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
run_capture() {
|
|
_name="$1"
|
|
shift
|
|
_out="${_raw_dir}/${_name}.txt"
|
|
note "collect ${_name}: $*"
|
|
{
|
|
printf '# command: %s\n' "$*"
|
|
printf '# collected_utc: %s\n\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
|
|
"$@"
|
|
} > "${_out}" 2>&1
|
|
_rc=$?
|
|
printf '\n# exit_status: %s\n' "${_rc}" >> "${_out}"
|
|
if [ "${_rc}" -ne 0 ]; then
|
|
note "WARN ${_name} exited ${_rc}"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
run_shell_capture() {
|
|
_name="$1"
|
|
_cmd="$2"
|
|
_out="${_raw_dir}/${_name}.txt"
|
|
note "collect ${_name}: ${_cmd}"
|
|
{
|
|
printf '# command: %s\n' "${_cmd}"
|
|
printf '# collected_utc: %s\n\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
|
|
/bin/sh -c "${_cmd}"
|
|
} > "${_out}" 2>&1
|
|
_rc=$?
|
|
printf '\n# exit_status: %s\n' "${_rc}" >> "${_out}"
|
|
if [ "${_rc}" -ne 0 ]; then
|
|
note "WARN ${_name} exited ${_rc}"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
run_if_present() {
|
|
_cmd="$1"
|
|
_name="$2"
|
|
shift 2
|
|
if have "${_cmd}"; then
|
|
run_capture "${_name}" "${_cmd}" "$@"
|
|
else
|
|
note "skip ${_name}: ${_cmd} not found"
|
|
fi
|
|
}
|
|
|
|
run_shell_if_present() {
|
|
_cmd="$1"
|
|
_name="$2"
|
|
_script="$3"
|
|
if have "${_cmd}"; then
|
|
run_shell_capture "${_name}" "${_script}"
|
|
else
|
|
note "skip ${_name}: ${_cmd} not found"
|
|
fi
|
|
}
|
|
|
|
json_escape() {
|
|
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
|
|
}
|
|
|
|
note "start ${_report_name}"
|
|
|
|
cat > "${_report_dir}/README.txt" <<'EOF'
|
|
Clawdie hardware report bundle
|
|
|
|
This is a local diagnostics bundle for FreeBSD/Clawdie live-USB support and
|
|
future custom ISO builds. It is not uploaded automatically.
|
|
|
|
Privacy notes:
|
|
- This bundle may contain hostnames, MAC addresses, disk model/serial strings,
|
|
USB/PCI IDs, kernel messages, local network interface state, Xorg/SDDM log
|
|
details, device names, and monitor EDID or serial-like strings.
|
|
- Review before sharing.
|
|
- Public hw-probe upload only happens when hw-report is run with
|
|
--upload-public-probe.
|
|
EOF
|
|
|
|
run_capture uname-a uname -a
|
|
run_if_present freebsd-version freebsd-version-kru -kru
|
|
run_capture hostname hostname
|
|
run_capture date-utc date -u '+%Y-%m-%dT%H:%M:%SZ'
|
|
run_if_present uptime uptime
|
|
|
|
run_if_present pciconf pciconf-lv -lv
|
|
run_if_present pciconf pciconf-lvbce -lvbce
|
|
run_if_present usbconfig usbconfig
|
|
run_if_present usbconfig usb-device-desc dump_device_desc
|
|
run_if_present usbconfig usb-all-desc dump_all_desc
|
|
run_if_present devinfo devinfo-rv -rv
|
|
run_if_present dmidecode dmidecode
|
|
run_if_present service dbus-status dbus onestatus
|
|
run_if_present service sddm-status sddm onestatus
|
|
|
|
run_if_present kldstat kldstat
|
|
run_if_present kldstat kldstat-v -v
|
|
run_if_present dmesg dmesg
|
|
run_shell_capture dmesg-hardware-filter "dmesg | egrep -i 'drm|kms|amdgpu|i915|radeon|nvidia|firmware|wifi|wlan|iwm|iwlwifi|rtwn|urtwn|run|otus|mt76|usb|uhub|ure|ue[0-9]|realtek|rtl|bluetooth|ubt|bcm|cypress|webcam|video|hid|iichid|hms|hmt|elan|touch|acpi|battery|powerd'"
|
|
run_shell_capture dmesg-boot "for f in /var/run/dmesg.boot; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture xorg-var-logs "for f in /var/log/Xorg.*.log*; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture xorg-user-logs "for f in /home/clawdie/.local/share/xorg/Xorg.*.log*; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture xsession-errors "for f in /home/clawdie/.xsession-errors /home/clawdie/.xsession-errors.old; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture var-log-messages "for f in /var/log/messages*; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; case \"\$f\" in *.gz) zcat \"\$f\";; *.bz2) bzcat \"\$f\";; *.xz) xzcat \"\$f\";; *.zst) zstdcat \"\$f\";; *) cat \"\$f\";; esac; echo; done"
|
|
run_shell_capture sddm-log-files "for f in /var/log/sddm.log; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture sddm-config "for f in /usr/local/etc/sddm.conf /usr/local/etc/sddm.conf.d/*; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture loader-conf-files "for f in /boot/loader.conf /boot/loader.conf.local; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_if_present kenv kenv
|
|
run_shell_capture xorg-config-snippets "for f in /usr/local/etc/X11/xorg.conf.d/* /etc/X11/xorg.conf.d/* /usr/local/share/X11/xorg.conf.d/*; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
|
|
run_if_present ifconfig ifconfig-a -a
|
|
run_if_present netstat netstat-rn -rn
|
|
run_shell_capture resolver-state "ls -l /etc/resolv.conf 2>/dev/null || true; readlink /etc/resolv.conf 2>/dev/null || true; cat /etc/resolv.conf 2>/dev/null || true"
|
|
run_shell_capture wlan-devices "sysctl net.wlan.devices"
|
|
run_shell_capture rc-conf-live "grep -E '^(hostname|kld_list|sshd_enable|tailscaled_enable|avahi_daemon_enable|pf_enable|sddm_enable|webcamd_enable|powerdxx_enable|colibri_daemon_enable|clawdie_live_|performance_cx_lowest|economy_cx_lowest|dumpdev_enable)' /etc/rc.conf || true"
|
|
run_if_present service service-enabled -e
|
|
|
|
run_if_present sysctl sysctl-hw hw
|
|
run_if_present sysctl sysctl-machdep machdep
|
|
run_shell_capture sysctl-selected "sysctl hw.acpi hw.dri kern.disks kern.geom net.wlan.devices dev.cpu 2>/dev/null || true"
|
|
run_shell_capture sysctl-drm-hw-dri "sysctl dev.drm hw.dri 2>/dev/null || true"
|
|
run_if_present service powerdxx-status powerdxx status
|
|
run_if_present sysctl snd-default-unit hw.snd.default_unit
|
|
run_if_present sysctl acpi-acline hw.acpi.acline
|
|
run_if_present sysctl acpi-cx-lowest hw.acpi.cpu.cx_lowest
|
|
run_if_present sysctl acpi-video-brightness hw.acpi.video.lcd0.brightness
|
|
run_shell_capture sysctl-input-stack "sysctl kern.evdev dev.iichid dev.hidbus dev.hms dev.hmt dev.hkbd dev.hconf dev.ig4 dev.psm dev.atkbd dev.uhid hw.psm 2>/dev/null || true"
|
|
run_if_present service moused-status moused onestatus
|
|
|
|
run_if_present gpart gpart-show show
|
|
run_if_present geom geom-disk-list disk list
|
|
run_if_present camcontrol camcontrol-devlist devlist
|
|
run_if_present nvmecontrol nvmecontrol-devlist devlist
|
|
run_if_present df df-h -h
|
|
run_if_present mount mount
|
|
run_if_present zpool zpool-list list
|
|
run_if_present zfs zfs-list list
|
|
|
|
if [ "${_run_smart}" = "YES" ] && have smartctl; then
|
|
_disks="$(sysctl -n kern.disks 2>/dev/null || true)"
|
|
if [ -n "${_disks}" ]; then
|
|
for _disk in ${_disks}; do
|
|
case "${_disk}" in
|
|
md*|cd*)
|
|
note "skip smartctl-${_disk}: virtual/removable class"
|
|
;;
|
|
*)
|
|
run_capture "smartctl-${_disk}" smartctl -a "/dev/${_disk}"
|
|
;;
|
|
esac
|
|
done
|
|
else
|
|
note "skip smartctl: kern.disks empty"
|
|
fi
|
|
else
|
|
note "skip smartctl: disabled or smartctl not found"
|
|
fi
|
|
|
|
run_if_present lspci lspci-nn -nn
|
|
run_if_present lsusb lsusb
|
|
run_if_present lscpu lscpu
|
|
run_if_present lsblk lsblk
|
|
run_if_present hwstat hwstat
|
|
run_shell_if_present usbhid-dump usbhid-dump-version "usbhid-dump --help 2>&1 | head -40"
|
|
|
|
run_if_present cat clawdie-live-gpu-log /var/log/clawdie-live-gpu.log
|
|
run_if_present cat clawdie-noblank-guard-log /home/clawdie/.clawdie-noblank-guard.log
|
|
run_if_present cat clawdie-touchpad-guard-log /home/clawdie/.clawdie-touchpad-guard.log
|
|
run_if_present cat sndstat /dev/sndstat
|
|
run_if_present mixer mixer-s -s
|
|
run_if_present v4l2-ctl v4l2-list-devices --list-devices
|
|
run_shell_capture video-devices "ls -l /dev/video* 2>/dev/null || true"
|
|
run_shell_capture dri-devices "ls -l /dev/dri /dev/dri/* 2>/dev/null || true"
|
|
run_shell_capture input-device-nodes "ls -l /dev/input /dev/input/* /dev/uhid* /dev/atp* 2>/dev/null || true"
|
|
|
|
run_if_present xset xset-q q
|
|
run_shell_if_present xfconf-query xfce4-power-manager "xfconf-query -c xfce4-power-manager -l -v 2>/dev/null || true"
|
|
run_shell_if_present xfconf-query xfce4-panel "xfconf-query -c xfce4-panel -l -v 2>/dev/null || true"
|
|
run_shell_if_present xfconf-query xfce4-desktop "xfconf-query -c xfce4-desktop -l -v 2>/dev/null || true"
|
|
run_shell_if_present xfconf-query xsettings "xfconf-query -c xsettings -l -v 2>/dev/null || true"
|
|
run_shell_if_present xfconf-query xfce4-pointers "DISPLAY=:0 XAUTHORITY=/home/clawdie/.Xauthority xfconf-query -c pointers -l -v 2>/dev/null || xfconf-query -c pointers -l -v 2>/dev/null || true"
|
|
run_shell_capture xfce-perchannel-xml "for f in /home/clawdie/.config/xfce4/xfconf/xfce-perchannel-xml/*; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture xfce-panel-launchers "find /home/clawdie/.config/xfce4/panel -maxdepth 4 -type f -print -exec sed -n '1,80p' {} \\; 2>/dev/null || true"
|
|
run_shell_capture icon-theme-dirs "find /usr/local/share/icons -maxdepth 4 -type f \( -name 'icon-theme.cache' -o -name 'clawdie-start.*' \) -print 2>/dev/null || true"
|
|
run_shell_capture clawdie-iso-assets "find /usr/local/share/clawdie-iso -maxdepth 4 -type f -ls 2>/dev/null || true; for f in /usr/local/share/clawdie-iso/build-manifest.json; do [ -e \"\$f\" ] || continue; echo \"===== \$f =====\"; cat \"\$f\"; echo; done"
|
|
run_shell_capture colibri-service-state "service colibri_daemon status 2>&1 || true; egrep -n '^(command|command_args|procname)=' /usr/local/etc/rc.d/colibri_daemon 2>/dev/null || true; sysrc -n colibri_daemon_enable 2>/dev/null || true"
|
|
if [ -f /home/clawdie/.Xauthority ]; then
|
|
run_shell_if_present xinput xinput-list "DISPLAY=:0 XAUTHORITY=/home/clawdie/.Xauthority xinput list 2>/dev/null || true"
|
|
run_shell_if_present xinput xinput-list-props "DISPLAY=:0 XAUTHORITY=/home/clawdie/.Xauthority sh -c 'for id in \$(xinput list --id-only 2>/dev/null); do echo \"===== device \$id =====\"; xinput list-props \"\$id\"; echo; done' || true"
|
|
run_shell_if_present xrandr xrandr-verbose "DISPLAY=:0 XAUTHORITY=/home/clawdie/.Xauthority xrandr --verbose 2>/dev/null || true"
|
|
run_shell_if_present glxinfo glxinfo-B "DISPLAY=:0 XAUTHORITY=/home/clawdie/.Xauthority glxinfo -B 2>/dev/null || true"
|
|
fi
|
|
run_shell_if_present libinput libinput-list-devices "libinput list-devices 2>/dev/null || true"
|
|
|
|
run_if_present vulkaninfo vulkaninfo-summary --summary
|
|
if have vulkaninfo && [ -f /home/clawdie/.Xauthority ]; then
|
|
run_shell_capture vulkaninfo-summary-display0 "DISPLAY=:0 XAUTHORITY=/home/clawdie/.Xauthority vulkaninfo --summary"
|
|
fi
|
|
|
|
run_if_present pkg pkg-info info
|
|
run_if_present pkg pkg-version version
|
|
run_if_present pkg pkg-audit audit
|
|
run_if_present hw-probe hw-probe-all -all
|
|
|
|
if [ "${_upload_public_probe}" = "YES" ]; then
|
|
if have hw-probe; then
|
|
run_capture hw-probe-all-upload hw-probe -all -upload
|
|
else
|
|
note "skip hw-probe public upload: hw-probe not found"
|
|
fi
|
|
else
|
|
note "public hw-probe upload not requested"
|
|
fi
|
|
|
|
_public_probe_urls=""
|
|
_public_probe_url=""
|
|
_upload_output="${_raw_dir}/hw-probe-all-upload.txt"
|
|
if [ -f "${_upload_output}" ]; then
|
|
_public_probe_urls="$(grep -Eo 'https?://[^[:space:]<>"'"'"']+' "${_upload_output}" | grep -E 'bsd-hardware\.info|linux-hardware\.org' | sort -u || true)"
|
|
_public_probe_url="$(printf '%s\n' "${_public_probe_urls}" | sed -n '1p')"
|
|
fi
|
|
|
|
_freebsd="$(freebsd-version -kru 2>/dev/null | tr '\n' ' ' | sed 's/[[:space:]]*$//')"
|
|
_gpu="$(pciconf -lv 2>/dev/null | grep -B3 -A4 -E 'VGA|display' | sed -n '1,12p')"
|
|
_wlan="$(sysctl -n net.wlan.devices 2>/dev/null || true)"
|
|
_disks="$(sysctl -n kern.disks 2>/dev/null || true)"
|
|
|
|
cat > "${_report_dir}/summary.txt" <<EOF
|
|
Clawdie hardware report
|
|
=======================
|
|
|
|
Report: ${_report_name}
|
|
Collected UTC: ${_stamp}
|
|
Host: ${_host}
|
|
FreeBSD: ${_freebsd}
|
|
Output directory: ${_report_dir}
|
|
Public hardware probe URL: ${_public_probe_url:-not uploaded or not reported by hw-probe}
|
|
|
|
Wireless parent devices:
|
|
${_wlan:-none reported}
|
|
|
|
Kernel disks:
|
|
${_disks:-none reported}
|
|
|
|
Display devices, first lines:
|
|
${_gpu:-none reported}
|
|
|
|
Share only after review. The bundle may include MAC addresses, serial strings,
|
|
local hostnames, and kernel/network state.
|
|
EOF
|
|
|
|
cat > "${_report_dir}/summary.json" <<EOF
|
|
{
|
|
"schema": "clawdie.hardware-report.v1",
|
|
"report_name": "$(json_escape "${_report_name}")",
|
|
"collected_utc": "$(json_escape "${_stamp}")",
|
|
"host": "$(json_escape "${_host}")",
|
|
"freebsd": "$(json_escape "${_freebsd}")",
|
|
"wlan_devices": "$(json_escape "${_wlan}")",
|
|
"kernel_disks": "$(json_escape "${_disks}")",
|
|
"public_probe_upload_requested": "${_upload_public_probe}",
|
|
"public_probe_url": "$(json_escape "${_public_probe_url}")",
|
|
"smart_probe_requested": "${_run_smart}",
|
|
"privacy_note": "local report; review before sharing"
|
|
}
|
|
EOF
|
|
|
|
_archive="${_base}/${_report_name}.tar.gz"
|
|
run_shell_capture report-file-list "find '${_report_dir}' -type f | sort"
|
|
if tar -czf "${_archive}" -C "${_base}" "${_report_name}" >> "${_log}" 2>&1; then
|
|
note "archive ${_archive}"
|
|
else
|
|
note "WARN archive failed: ${_archive}"
|
|
fi
|
|
|
|
if [ -d /home/clawdie ] && id clawdie >/dev/null 2>&1; then
|
|
chown -R clawdie:clawdie "${_base}" 2>/dev/null || true
|
|
fi
|
|
|
|
cat <<EOF
|
|
|
|
Clawdie hardware report complete.
|
|
|
|
Summary:
|
|
${_report_dir}/summary.txt
|
|
JSON:
|
|
${_report_dir}/summary.json
|
|
Archive:
|
|
${_archive}
|
|
EOF
|
|
|
|
if [ "${_upload_public_probe}" = "YES" ]; then
|
|
if [ -n "${_public_probe_url}" ]; then
|
|
cat <<EOF
|
|
Public hardware probe:
|
|
${_public_probe_url}
|
|
EOF
|
|
else
|
|
cat <<EOF
|
|
Public hardware probe upload was requested, but no public URL was detected.
|
|
Inspect:
|
|
${_upload_output}
|
|
EOF
|
|
fi
|
|
else
|
|
cat <<EOF
|
|
|
|
Review before sharing. To include a public bsd-hardware.info probe URL, rerun:
|
|
mdo -u root hw-report --upload-public-probe
|
|
EOF
|
|
fi
|
|
|
|
exit 0
|