Files
device_agent/capability_proc.go
T
2026-05-30 17:28:38 +02:00

104 lines
2.5 KiB
Go

package main
import (
"context"
"fmt"
"os/exec"
"runtime"
"strconv"
"strings"
"time"
)
const procMaxEntries = 200
// runProcList enumera procesos. En linux usa /proc parsing via `ps -eo`.
func runProcList(cap *Capability, args map[string]any) (any, int, error) {
_ = cap
_ = args
if runtime.GOOS == "windows" {
return runProcListWindows()
}
return runProcListUnix()
}
func runProcListUnix() (any, int, error) {
if _, err := exec.LookPath("ps"); err != nil {
return nil, -1, fmt.Errorf("ps binary not found")
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// ps -eo pid,ppid,user,comm,rss,pcpu --no-headers
c := exec.CommandContext(ctx, "ps", "-eo", "pid,ppid,user,comm,rss,pcpu", "--no-headers")
out, err := c.Output()
if err != nil {
return nil, -1, fmt.Errorf("ps: %w", err)
}
lines := strings.Split(string(out), "\n")
processes := []map[string]any{}
for _, line := range lines {
fields := strings.Fields(line)
if len(fields) < 6 {
continue
}
pid, _ := strconv.Atoi(fields[0])
ppid, _ := strconv.Atoi(fields[1])
user := fields[2]
name := fields[3]
rss, _ := strconv.ParseInt(fields[4], 10, 64)
cpu, _ := strconv.ParseFloat(fields[5], 64)
processes = append(processes, map[string]any{
"pid": pid,
"ppid": ppid,
"user": user,
"name": name,
"rss_kb": rss,
"cpu_pct": cpu,
})
if len(processes) >= procMaxEntries {
break
}
}
return map[string]any{
"processes": processes,
"count": len(processes),
"truncated": len(processes) >= procMaxEntries,
}, 0, nil
}
func runProcListWindows() (any, int, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
c := exec.CommandContext(ctx, "tasklist", "/FO", "CSV", "/NH")
out, err := c.Output()
if err != nil {
return nil, -1, fmt.Errorf("tasklist: %w", err)
}
lines := strings.Split(string(out), "\n")
processes := []map[string]any{}
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
parts := strings.Split(line, ",")
if len(parts) < 5 {
continue
}
name := strings.Trim(parts[0], `"`)
pid, _ := strconv.Atoi(strings.Trim(parts[1], `"`))
processes = append(processes, map[string]any{
"pid": pid,
"name": name,
})
if len(processes) >= procMaxEntries {
break
}
}
return map[string]any{
"processes": processes,
"count": len(processes),
"truncated": len(processes) >= procMaxEntries,
}, 0, nil
}