// cmd/sysusage/main.go package main import ( "encoding/json" "flag" "fmt" "log" "time" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/mem" ) type Result struct { CPUPercent float64 `json:"cpu_percent"` RAMPercent float64 `json:"ram_percent"` } func sampleCPU(interval time.Duration, samples int) (float64, error) { if samples <= 0 { samples = 1 } var sum float64 for i := 0; i < samples; i++ { // cpu.Percent blockiert für "interval" und liefert die Auslastung in diesem Zeitfenster values, err := cpu.Percent(interval, false) if err != nil { return 0, err } if len(values) == 0 { return 0, fmt.Errorf("no cpu values returned") } sum += values[0] } return sum / float64(samples), nil } func readRAM() (float64, error) { vm, err := mem.VirtualMemory() if err != nil { return 0, err } return vm.UsedPercent, nil } func main() { var ( intervalStr string samples int jsonOut bool watch bool ) flag.StringVar(&intervalStr, "interval", "1s", "Messintervall pro Stichprobe (z.B. 200ms, 1s, 2s)") flag.IntVar(&samples, "samples", 1, "Anzahl der Stichproben (über das Intervall gemittelt)") flag.BoolVar(&jsonOut, "json", false, "Ausgabe als JSON") flag.BoolVar(&watch, "watch", false, "Kontinuierlich messen, bis Strg+C") flag.Parse() interval, err := time.ParseDuration(intervalStr) if err != nil || interval <= 0 { log.Fatalf("ungültiges -interval: %v", intervalStr) } printOnce := func() error { cpuPct, err := sampleCPU(interval, samples) if err != nil { return fmt.Errorf("CPU-Messung fehlgeschlagen: %w", err) } ramPct, err := readRAM() if err != nil { return fmt.Errorf("RAM-Messung fehlgeschlagen: %w", err) } if jsonOut { out := Result{CPUPercent: cpuPct, RAMPercent: ramPct} enc := json.NewEncoder(stdoutNoHTMLEscape{}) enc.SetIndent("", " ") return enc.Encode(out) } fmt.Printf("CPU: %.1f%% | RAM: %.1f%%\n", cpuPct, ramPct) return nil } if watch { for { if err := printOnce(); err != nil { log.Fatal(err) } // Bei watch: zwischen den Zeilen kurz pausieren, damit die Ausgabe lesbar bleibt. time.Sleep(250 * time.Millisecond) } } else { if err := printOnce(); err != nil { log.Fatal(err) } } } // stdoutNoHTMLEscape verhindert das HTML-Escaping des Standard-Encoders (nur Kosmetik für JSON) type stdoutNoHTMLEscape struct{} func (stdoutNoHTMLEscape) Write(p []byte) (int, error) { return fmt.Print(string(p)) } func (stdoutNoHTMLEscape) Encode(v any) error { enc := json.NewEncoder(stdoutNoHTMLEscape{}) enc.SetEscapeHTML(false) return enc.Encode(v) }