#!/bin/bash # Gather system information from a remote server # Output format: [section] headers followed by key=value pairs echo "[system]" echo "hostname=$(hostname)" if [ -f /etc/os-release ]; then . /etc/os-release echo "os_name=$NAME" echo "os_version=$VERSION_ID" echo "os_pretty=$PRETTY_NAME" fi echo "kernel=$(uname -r)" echo "arch=$(uname -m)" echo "uptime_seconds=$(cut -d' ' -f1 /proc/uptime 2>/dev/null | cut -d. -f1)" # Motherboard (readable without root on most systems) echo "board_vendor=$(cat /sys/class/dmi/id/board_vendor 2>/dev/null || echo 'Unknown')" echo "board_name=$(cat /sys/class/dmi/id/board_name 2>/dev/null || echo 'Unknown')" echo "board_version=$(cat /sys/class/dmi/id/board_version 2>/dev/null || echo 'Unknown')" echo "bios_version=$(cat /sys/class/dmi/id/bios_version 2>/dev/null || echo 'Unknown')" echo "bios_date=$(cat /sys/class/dmi/id/bios_date 2>/dev/null || echo 'Unknown')" echo "[cpu]" echo "model=$(lscpu 2>/dev/null | grep 'Model name' | sed 's/Model name:[[:space:]]*//')" echo "cores=$(nproc 2>/dev/null || echo 0)" echo "sockets=$(lscpu 2>/dev/null | grep 'Socket(s)' | awk '{print $2}')" echo "threads_per_core=$(lscpu 2>/dev/null | grep 'Thread(s) per core' | awk '{print $2}')" # CPU usage - sample /proc/stat with 1 second interval read -r label user1 nice1 system1 idle1 iowait1 irq1 softirq1 steal1 < /proc/stat sleep 1 read -r label user2 nice2 system2 idle2 iowait2 irq2 softirq2 steal2 < /proc/stat total1=$((user1 + nice1 + system1 + idle1 + iowait1 + irq1 + softirq1 + steal1)) total2=$((user2 + nice2 + system2 + idle2 + iowait2 + irq2 + softirq2 + steal2)) diff_total=$((total2 - total1)) diff_idle=$((idle2 - idle1)) if [ $diff_total -gt 0 ]; then usage_x10=$(( (diff_total - diff_idle) * 1000 / diff_total )) whole=$((usage_x10 / 10)) frac=$((usage_x10 % 10)) echo "usage_percent=${whole}.${frac}" else echo "usage_percent=0.0" fi echo "[memory]" total_kb=$(grep MemTotal /proc/meminfo 2>/dev/null | awk '{print $2}') available_kb=$(grep MemAvailable /proc/meminfo 2>/dev/null | awk '{print $2}') if [ -n "$total_kb" ] && [ -n "$available_kb" ]; then used_kb=$((total_kb - available_kb)) total_mb=$((total_kb / 1024)) used_mb=$((used_kb / 1024)) available_mb=$((available_kb / 1024)) if [ "$total_kb" -gt 0 ]; then usage_x10=$((used_kb * 1000 / total_kb)) whole=$((usage_x10 / 10)) frac=$((usage_x10 % 10)) echo "usage_percent=${whole}.${frac}" else echo "usage_percent=0.0" fi echo "total_mb=$total_mb" echo "used_mb=$used_mb" echo "available_mb=$available_mb" fi # Physical disks lsblk -b -n -o NAME,SIZE,TYPE 2>/dev/null | while read -r name size type; do if [ "$type" = "disk" ]; then echo "[disk:$name]" echo "name=$name" echo "size_bytes=$size" fi done # Mounted filesystem usage df -B1 --output=target,size,used,avail,pcent 2>/dev/null | tail -n +2 | while read -r mount total used avail percent; do case "$mount" in /|/home|/var|/tmp|/boot|/data*|/mnt*|/srv*|/opt*) safename=$(echo "$mount" | tr '/' '_') echo "[disk_usage:${safename}]" echo "mount=$mount" echo "total_bytes=$total" echo "used_bytes=$used" echo "available_bytes=$avail" echo "usage_percent=${percent%\%}" ;; esac done # GPUs gpu_idx=0 while read -r line; do echo "[gpu:$gpu_idx]" echo "description=$line" gpu_idx=$((gpu_idx + 1)) done < <(lspci 2>/dev/null | grep -iE 'vga|3d|display') # Network interfaces for iface in $(ls /sys/class/net/ 2>/dev/null); do [ "$iface" = "lo" ] && continue echo "[net:$iface]" echo "name=$iface" echo "mac=$(cat /sys/class/net/$iface/address 2>/dev/null)" echo "ipv4=$(ip -4 addr show "$iface" 2>/dev/null | grep -oP 'inet \K[0-9.]+' | head -1)" echo "ipv6=$(ip -6 addr show "$iface" 2>/dev/null | grep -oP 'inet6 \K[0-9a-f:]+' | grep -v '^fe80' | head -1)" echo "state=$(cat /sys/class/net/$iface/operstate 2>/dev/null)" speed=$(cat /sys/class/net/$iface/speed 2>/dev/null) [ -n "$speed" ] && [ "$speed" != "-1" ] && echo "speed_mbps=$speed" driver=$(readlink /sys/class/net/$iface/device/driver 2>/dev/null | xargs basename 2>/dev/null) [ -n "$driver" ] && echo "driver=$driver" done echo "[routing]" default_line=$(ip route 2>/dev/null | grep default | head -1) echo "gateway=$(echo "$default_line" | awk '{print $3}')" echo "interface=$(echo "$default_line" | awk '{print $5}')" echo "[dns]" grep -E '^nameserver' /etc/resolv.conf 2>/dev/null | awk '{print "server=" $2}' echo "[tailscale]" if command -v tailscale &>/dev/null; then echo "installed=true" echo "ipv4=$(tailscale ip -4 2>/dev/null)" echo "hostname=$(tailscale status --self --json 2>/dev/null | grep -o '"DNSName":"[^"]*"' | head -1 | cut -d'"' -f4)" else echo "installed=false" fi echo "[end]"