104 lines
2.5 KiB
Go
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
|
|
}
|