summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-14 17:29:08 +0200
committerPaul Buetow <paul@buetow.org>2026-02-14 17:29:08 +0200
commitb1f0ce01fb6ece8628cf0499690a003cdac28f7f (patch)
treece67d7633075743cd057031c21dca81834494be8
parentef236805d7c7f655ef22da08d708ecb85212c15c (diff)
Remove macOS stats gathering support, require Linux with /procv0.8.4
Remove non-functional macOS monitoring code that used native tools (sysctl, vm_stat, netstat, iostat). Now loadbars exits with an error when attempting local stats gathering on non-Linux systems. macOS can still be used as a client to monitor remote Linux servers via SSH.
-rw-r--r--AGENTS.md18
-rw-r--r--README.md4
-rw-r--r--internal/collector/collector.go13
-rw-r--r--internal/collector/loadbars-remote-darwin.sh77
-rw-r--r--internal/collector/script.go5
-rw-r--r--internal/version/version.go2
6 files changed, 17 insertions, 102 deletions
diff --git a/AGENTS.md b/AGENTS.md
index 63531fd..ab005e5 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -66,33 +66,27 @@ Network interface: chosen by `netint` config or first non-`lo`; press `n` to cyc
- `go test ./...` or `mage test`. No UI tests; collector has parse tests for protocol (e.g. `ParseNetLine` for Linux-style `/proc/net/dev` output).
-## macOS support
+## macOS support (client only)
-Loadbars supports macOS with automatic window activation and OS-specific monitoring scripts.
+Loadbars supports macOS as a client to monitor remote Linux servers via SSH.
### Implementation details
-- **Script embedding:** Both Linux and Darwin monitoring scripts are embedded in the binary
-- **OS detection:** Automatically uses the correct script based on the host:
- - `localhost` on macOS → Darwin script (sysctl, vm_stat, netstat, iostat)
- - `localhost` on Linux → Linux script (/proc filesystem)
- - All remote hosts → Linux script (assumes remote servers are Linux)
- **Window activation:** macOS-specific code automatically brings SDL window to foreground
- Uses build tags (`activate_darwin.go` and `activate.go`)
- No external helper script needed
### Key files
-- `internal/collector/script.go` - Embeds both scripts
-- `internal/collector/collector.go` - Selects script based on host (checks if `/proc` exists for localhost)
+- `internal/collector/script.go` - Embeds the Linux monitoring script
+- `internal/collector/collector.go` - Runs Linux script locally or over SSH; exits with error if local system lacks /proc
- `internal/display/activate_darwin.go` - macOS-specific activation using `open -a`
- `internal/display/activate.go` - No-op for other platforms
### Known limitations
-- Remote macOS hosts are not supported (assumes all remote hosts are Linux)
-- macOS script doesn't provide per-core CPU statistics (iostat limitation)
-- Swap usage on macOS always shows 0 (macOS uses compressed memory differently)
+- Local monitoring on macOS is not supported (requires Linux with /proc filesystem)
+- All remote hosts must be Linux (assumes all remote hosts are Linux)
## Useful references
diff --git a/README.md b/README.md
index fb3fe53..5fe02ea 100644
--- a/README.md
+++ b/README.md
@@ -10,9 +10,9 @@ Loadbars is a tool that can be used to observe CPU loads of several remote serve
This version of loadbars has been tested on:
- Fedora Linux 43 and most modern Linux distributions (RHEL, CentOS, Ubuntu, Debian, etc.)
-- macOS (Darwin) - localhost monitoring uses native macOS tools (sysctl, vm_stat, netstat, iostat)
+- macOS (Darwin) - can connect to remote Linux servers via SSH (local monitoring not supported)
-**Note:** Remote hosts are assumed to be Linux (using /proc filesystem). When running on macOS, localhost monitoring uses macOS-specific commands, while remote hosts use the Linux script. So remote hosts only work with Linux.
+**Note:** Local monitoring requires Linux with /proc filesystem. Remote hosts must be Linux (using /proc filesystem). macOS can be used as a client to monitor remote Linux servers.
## Build and run
diff --git a/internal/collector/collector.go b/internal/collector/collector.go
index cab9df0..91f3d7b 100644
--- a/internal/collector/collector.go
+++ b/internal/collector/collector.go
@@ -25,13 +25,16 @@ type StatsStore interface {
// The script is embedded in the binary; no external script file is required.
func Run(ctx context.Context, host string, cfg *config.Config, store StatsStore) error {
hostKey, user := splitHostUser(host)
-
- // Select script: Darwin for localhost on macOS, Linux for everything else (all remotes are Linux)
+
+ // Select script: Only Linux supported for local monitoring
scriptBytes := LinuxScript
if isLocal(hostKey) {
scriptBytes = getLocalScript()
+ if scriptBytes == nil {
+ return fmt.Errorf("%s: local stats gathering requires Linux with /proc filesystem", hostKey)
+ }
}
-
+
script := bytes.NewReader(scriptBytes)
var scanner *bufio.Scanner
if isLocal(hostKey) {
@@ -135,6 +138,6 @@ func getLocalScript() []byte {
if _, err := exec.Command("test", "-d", "/proc").CombinedOutput(); err == nil {
return LinuxScript
}
- // Otherwise assume macOS
- return DarwinScript
+ // /proc not found - unsupported OS for local stats gathering
+ return nil
}
diff --git a/internal/collector/loadbars-remote-darwin.sh b/internal/collector/loadbars-remote-darwin.sh
deleted file mode 100644
index f82c802..0000000
--- a/internal/collector/loadbars-remote-darwin.sh
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/bash
-# loadbars-remote-darwin.sh - macOS version using sysctl, vm_stat, netstat, and iostat
-# Emits loadbars protocol (M LOADAVG, M MEMSTATS, M NETSTATS, M CPUSTATS)
-# Interval for CPU sampling (seconds)
-INTERVAL=0.14
-
-# Get number of CPUs
-NCPU=$(sysctl -n hw.ncpu)
-
-while true; do
- # Load average: from sysctl
- echo "M LOADAVG"
- sysctl -n vm.loadavg 2>/dev/null | awk '{print $2";"$3";"$4}' || echo "0;0;0"
-
- # Memory: convert vm_stat output to /proc/meminfo-like format
- echo "M MEMSTATS"
- vm_stat 2>/dev/null | awk '
- BEGIN { pagesize = 4096 }
- /page size of ([0-9]+)/ { pagesize = $8 }
- /Pages free:/ { free = $3 * pagesize / 1024 }
- /Pages active:/ { active = $3 * pagesize / 1024 }
- /Pages inactive:/ { inactive = $3 * pagesize / 1024 }
- /Pages speculative:/ { speculative = $3 * pagesize / 1024 }
- /Pages wired down:/ { wired = $4 * pagesize / 1024 }
- /Pages occupied by compressor:/ { compressed = $5 * pagesize / 1024 }
- END {
- total = free + active + inactive + speculative + wired + compressed
- printf "MemTotal: %d kB\n", total
- printf "MemFree: %d kB\n", free
- printf "MemAvailable: %d kB\n", free + inactive + speculative
- printf "SwapTotal: 0 kB\n"
- printf "SwapFree: 0 kB\n"
- }
- '
-
- # Network: use netstat -ibn for interface stats
- echo "M NETSTATS"
- netstat -ibn 2>/dev/null | awk '
- NR > 1 && $1 !~ /^Name/ && $3 ~ /^<Link/ {
- # netstat -ibn output on macOS:
- # Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll
- iface = $1
- ipkts = $5
- ierrs = $6
- ibytes = $7
- opkts = $8
- oerrs = $9
- obytes = $10
-
- if (ibytes ~ /^[0-9]+$/ && obytes ~ /^[0-9]+$/) {
- printf "%s:b=%s;tb=%s;p=%s;tp=%s e=%s;te=%s;d=0;td=0\n",
- iface, ibytes, obytes, ipkts, opkts, ierrs, oerrs
- }
- }
- '
-
- # CPU: macOS doesn't have /proc/stat, use iostat for CPU percentages
- echo "M CPUSTATS"
- for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
- # iostat output on macOS: user sys idle
- # Convert to /proc/stat format: cpu user nice system idle iowait irq softirq steal guest guest_nice
- # We'll simulate values since macOS doesn't provide all fields
- iostat -c 1 2>/dev/null | tail -1 | awk -v ncpu="$NCPU" '
- {
- # iostat columns: %user %nice %sys %idle (approximately)
- # Multiply by ncpu to get total ticks (simulated)
- user = int($3 * ncpu * 10)
- sys = int($4 * ncpu * 10)
- idle = int($5 * ncpu * 10)
-
- # Output in /proc/stat format
- printf "cpu %d 0 %d %d 0 0 0 0 0 0\n", user, sys, idle
- }
- '
- sleep "$INTERVAL" 2>/dev/null || true
- done
-done
diff --git a/internal/collector/script.go b/internal/collector/script.go
index 3be2190..5dc9dce 100644
--- a/internal/collector/script.go
+++ b/internal/collector/script.go
@@ -6,8 +6,3 @@ import _ "embed"
//
//go:embed loadbars-remote.sh
var LinuxScript []byte
-
-// DarwinScript contains the embedded loadbars-remote-darwin.sh script for macOS hosts
-//
-//go:embed loadbars-remote-darwin.sh
-var DarwinScript []byte
diff --git a/internal/version/version.go b/internal/version/version.go
index 67d9c60..2b4ace2 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -1,4 +1,4 @@
package version
// Version is the application version (set at build time or here for development).
-const Version = "0.8.3"
+const Version = "0.8.4"