Dotfiles/desktopenvs/hyprdrive/astro-menu/backend/sysmon.sh

102 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# astro-menu system-monitor backend — the ship's "Systems Diagnostic".
# Emits one TAB-separated record per subsystem:
#
# CATEGORY <TAB> NAME <TAB> USAGE_PCT <TAB> TEMP_C <TAB> DETAIL
#
# CATEGORY is cpu|gpu|ram|disk (drives the icon). USAGE_PCT is 0..100. TEMP_C is
# an integer °C or empty when no sensor exists. One `disk` row per mounted real
# filesystem. Reads everything from /proc + /sys (no extra deps).
set -uo pipefail
milli_to_c() { awk '{printf "%d", ($1 + 500) / 1000}'; }
hwmon_temp() { # $1 = chip-name substring; first temp input of that chip, in °C
local h n t
for h in /sys/class/hwmon/hwmon*; do
n=$(cat "$h/name" 2>/dev/null) || continue
[[ "$n" == *"$1"* ]] || continue
for t in "$h"/temp*_input; do
[[ -r "$t" ]] && { milli_to_c < "$t"; return 0; }
done
done
return 1
}
hwmon_dir_temp() { # $1 = hwmon dir, $2 = preferred label substring
local d="$1" pref="$2" lf lbl base
for lf in "$d"/temp*_label; do
[[ -r "$lf" ]] || continue
[[ "$(cat "$lf" 2>/dev/null)" == *"$pref"* ]] || continue
base="${lf%_label}_input"
[[ -r "$base" ]] && { milli_to_c < "$base"; return 0; }
done
for base in "$d"/temp*_input; do
[[ -r "$base" ]] && { milli_to_c < "$base"; return 0; }
done
return 1
}
nvme_temp() { # $1 = disk (e.g. nvme0n1); temp of that specific controller, in °C
local ctrl h t
ctrl=$(basename "$(readlink -f "/sys/block/$1/device" 2>/dev/null)")
for h in /sys/class/hwmon/hwmon*; do
[[ "$(cat "$h/name" 2>/dev/null)" == "nvme" ]] || continue
[[ "$(basename "$(readlink -f "$h/device" 2>/dev/null)")" == "$ctrl" ]] || continue
for t in "$h"/temp*_input; do
[[ -r "$t" ]] && { milli_to_c < "$t"; return 0; }
done
done
return 1
}
# --- CPU: Thrusters ---------------------------------------------------------
cpu_snapshot() { awk '/^cpu /{t=0; for (i=2; i<=NF; i++) t+=$i; print t, $5}' /proc/stat; }
read t1 idle1 < <(cpu_snapshot); sleep 0.2; read t2 idle2 < <(cpu_snapshot)
dtotal=$(( t2 - t1 )); didle=$(( idle2 - idle1 )); cpu_usage=0
(( dtotal > 0 )) && cpu_usage=$(( ((dtotal - didle) * 100 + dtotal / 2) / dtotal ))
cpu_temp=$(hwmon_temp k10temp) || cpu_temp=$(hwmon_temp coretemp) || cpu_temp=""
printf 'cpu\tThrusters\t%s\t%s\t%s cores online\n' "$cpu_usage" "$cpu_temp" "$(nproc 2>/dev/null || echo '?')"
# --- GPU: Hyperdrive (discrete = the card with the most VRAM) ---------------
gpu_dev=""; best_vram=-1
for d in /sys/class/drm/card[0-9]*/device; do
[[ -r "$d/gpu_busy_percent" ]] || continue
v=$(cat "$d/mem_info_vram_total" 2>/dev/null || echo 0)
(( v > best_vram )) && { best_vram=$v; gpu_dev=$d; }
done
gpu_usage=0; gpu_temp=""; gpu_detail="offline"
if [[ -n "$gpu_dev" ]]; then
gpu_usage=$(cat "$gpu_dev/gpu_busy_percent" 2>/dev/null || echo 0)
for hd in "$gpu_dev"/hwmon/hwmon*; do
[[ -d "$hd" ]] && { gpu_temp=$(hwmon_dir_temp "$hd" junction) || gpu_temp=""; break; }
done
(( best_vram > 0 )) && gpu_detail=$(awk -v b="$best_vram" 'BEGIN{printf "%.0f GiB core", b/1073741824}')
fi
printf 'gpu\tHyperdrive\t%s\t%s\t%s\n' "$gpu_usage" "$gpu_temp" "$gpu_detail"
# --- RAM: Life Support Systems ---------------------------------------------
read ram_used ram_total < <(free -b | awk '/^Mem:/{print $3, $2}')
ram_usage=0; (( ram_total > 0 )) && ram_usage=$(( (ram_used * 100 + ram_total / 2) / ram_total ))
ram_temp=$(hwmon_temp spd5118) || ram_temp=$(hwmon_temp jc42) || ram_temp=""
ram_detail=$(awk -v u="$ram_used" -v t="$ram_total" 'BEGIN{printf "%.1f/%.1f GiB", u/1073741824, t/1073741824}')
printf 'ram\tLife Support Systems\t%s\t%s\t%s\n' "$ram_usage" "$ram_temp" "$ram_detail"
# --- Storage: Cargo Hold (one row per real filesystem, deduped by device) ---
declare -A seen
while read -r src used size; do
[[ "$src" == /dev/* ]] || continue
[[ -n "${seen[$src]:-}" ]] && continue
seen[$src]=1
dev=$(basename "$src") # e.g. sda1 / nvme0n1p2
disk=$(lsblk -no pkname "$src" 2>/dev/null | head -1) # parent disk, if partitioned
[[ -z "$disk" ]] && disk="$dev"
(( size > 0 )) || continue
usage=$(( (used * 100 + size / 2) / size ))
temp=""; [[ "$disk" == nvme* ]] && { temp=$(nvme_temp "$disk") || temp=""; }
[[ -z "$temp" ]] && temp=$(hwmon_temp drivetemp 2>/dev/null) || true
detail=$(awk -v d="$dev" -v u="$used" -v t="$size" \
'BEGIN{printf "%-10s %.0f/%.0f GiB", d, u/1073741824, t/1073741824}')
printf 'disk\tCargo Hold\t%s\t%s\t%s\n' "$usage" "$temp" "$detail"
done < <(df -B1 --output=source,used,size -x tmpfs -x devtmpfs -x overlay -x squashfs 2>/dev/null | tail -n +2)