- Calibrate: per-event Telegram/SMTP toggles, test notification, chat ID help - Notify on agent connect/reconnect, offline/hashrate/rejection, forge complete - Sigil scramble post-forge uniquification and Dispense Reveal ceremony - Full system check, desktop push, BITS/host-binary persistence, Path Tracer - Dashboard/Crucible visual polish, haptics, sacred geometry, mobile nav - README documents alerts, sigil scramble, and pack-usb workflow - USB bundle repacked via pack-usb.bat (AetherForge.exe + synced agent source)
139 lines
3.7 KiB
Go
139 lines
3.7 KiB
Go
//go:build !windows
|
|
|
|
package client
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"os/user"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func collectSysCheckPlatform(r *FullSysCheckReport) {
|
|
hw := &SysCheckHardware{}
|
|
|
|
if out, err := exec.Command("uname", "-a").CombinedOutput(); err == nil {
|
|
parts := strings.Fields(string(out))
|
|
if len(parts) >= 3 {
|
|
hw.Manufacturer = parts[2]
|
|
}
|
|
}
|
|
|
|
if runtime.GOOS == "darwin" {
|
|
if out, err := exec.Command("sysctl", "-n", "hw.model").CombinedOutput(); err == nil {
|
|
hw.Model = strings.TrimSpace(string(out))
|
|
}
|
|
if out, err := exec.Command("sysctl", "-n", "hw.memsize").CombinedOutput(); err == nil {
|
|
if n, err := strconv.ParseInt(strings.TrimSpace(string(out)), 10, 64); err == nil {
|
|
hw.MemoryGB = float64(n) / (1024 * 1024 * 1024)
|
|
}
|
|
}
|
|
} else {
|
|
if out, err := exec.Command("sh", "-c", "grep -m1 'model name' /proc/cpuinfo | cut -d: -f2").CombinedOutput(); err == nil {
|
|
hw.CPUs = []SysCheckCPU{{Name: strings.TrimSpace(string(out))}}
|
|
}
|
|
if out, err := exec.Command("sh", "-c", "grep -c ^processor /proc/cpuinfo").CombinedOutput(); err == nil {
|
|
if n, err := strconv.Atoi(strings.TrimSpace(string(out))); err == nil && len(hw.CPUs) > 0 {
|
|
hw.CPUs[0].Logical = n
|
|
}
|
|
}
|
|
if out, err := exec.Command("free", "-b").CombinedOutput(); err == nil {
|
|
lines := strings.Split(string(out), "\n")
|
|
if len(lines) > 1 {
|
|
fields := strings.Fields(lines[1])
|
|
if len(fields) >= 2 {
|
|
if total, err := strconv.ParseInt(fields[1], 10, 64); err == nil {
|
|
hw.MemoryGB = float64(total) / (1024 * 1024 * 1024)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if out, err := exec.Command("df", "-h").CombinedOutput(); err == nil {
|
|
hw.Disks = parseDfOutput(string(out))
|
|
}
|
|
|
|
if out, err := exec.Command("sh", "-c", "cat /proc/uptime 2>/dev/null || sysctl -n kern.boottime 2>/dev/null").CombinedOutput(); err == nil {
|
|
fields := strings.Fields(string(out))
|
|
if len(fields) > 0 {
|
|
if sec, err := strconv.ParseFloat(fields[0], 64); err == nil {
|
|
hw.UptimeHours = sec / 3600
|
|
}
|
|
}
|
|
}
|
|
|
|
r.Hardware = hw
|
|
|
|
if r.Identity == nil {
|
|
r.Identity = &SysCheckIdentity{}
|
|
}
|
|
if u, err := user.Current(); err == nil {
|
|
r.Identity.Username = u.Username
|
|
}
|
|
r.Identity.MACAddress = primaryMACAddress()
|
|
|
|
if r.Environment == nil {
|
|
r.Environment = &SysCheckEnvironment{}
|
|
}
|
|
r.Environment.HomeDir = os.Getenv("HOME")
|
|
r.Environment.TempDir = os.Getenv("TMPDIR")
|
|
if r.Environment.TempDir == "" {
|
|
r.Environment.TempDir = "/tmp"
|
|
}
|
|
|
|
if r.Network == nil {
|
|
r.Network = &SysCheckNetwork{}
|
|
}
|
|
if out, err := exec.Command("sh", "-c", "ip route show default 2>/dev/null || route -n get default 2>/dev/null").CombinedOutput(); err == nil {
|
|
r.Network.RoutesSummary = strings.TrimSpace(string(out))
|
|
for _, line := range strings.Split(string(out), "\n") {
|
|
if strings.Contains(line, "via") || strings.Contains(line, "gateway:") {
|
|
fields := strings.Fields(line)
|
|
for i, f := range fields {
|
|
if f == "via" && i+1 < len(fields) {
|
|
r.Network.DefaultGateway = fields[i+1]
|
|
break
|
|
}
|
|
if strings.HasPrefix(f, "gateway:") {
|
|
r.Network.DefaultGateway = strings.TrimPrefix(f, "gateway:")
|
|
break
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func parseDfOutput(raw string) []SysCheckDisk {
|
|
var disks []SysCheckDisk
|
|
for _, line := range strings.Split(raw, "\n")[1:] {
|
|
fields := strings.Fields(line)
|
|
if len(fields) < 6 {
|
|
continue
|
|
}
|
|
mount := fields[len(fields)-1]
|
|
disks = append(disks, SysCheckDisk{
|
|
Mount: mount,
|
|
FSType: fields[0],
|
|
TotalGB: parseSizeGB(fields[1]),
|
|
FreeGB: parseSizeGB(fields[3]),
|
|
})
|
|
}
|
|
return disks
|
|
}
|
|
|
|
func parseSizeGB(s string) float64 {
|
|
s = strings.TrimSuffix(s, "G")
|
|
s = strings.TrimSuffix(s, "T")
|
|
s = strings.TrimSuffix(s, "M")
|
|
f, _ := strconv.ParseFloat(s, 64)
|
|
if strings.HasSuffix(s, "T") {
|
|
return f * 1024
|
|
}
|
|
return f
|
|
}
|