mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-04 18:51:17 +00:00
78 lines
1.6 KiB
Go
78 lines
1.6 KiB
Go
package procspy
|
|
|
|
// lsof-executing implementation.
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
lsofFields = "cn" // parseLSOF() depends on the order
|
|
)
|
|
|
|
// parseLsof parses lsof out with `-F cn` argument.
|
|
//
|
|
// Format description: the first letter is the type of record, records are
|
|
// newline separated, the record starting with 'p' (pid) is a new processid.
|
|
// There can be multiple connections for the same 'p' record in which case the
|
|
// 'p' is not repeated.
|
|
//
|
|
// For example, this is one process with two listens and one connection:
|
|
//
|
|
// p13100
|
|
// cmpd
|
|
// n[::1]:6600
|
|
// n127.0.0.1:6600
|
|
// n[::1]:6600->[::1]:50992
|
|
//
|
|
func parseLSOF(out string) (map[string]Proc, error) {
|
|
var (
|
|
res = map[string]Proc{} // Local addr -> Proc
|
|
cp = Proc{}
|
|
)
|
|
for _, line := range strings.Split(out, "\n") {
|
|
if len(line) <= 1 {
|
|
continue
|
|
}
|
|
|
|
var (
|
|
field = line[0]
|
|
value = line[1:]
|
|
)
|
|
switch field {
|
|
case 'p':
|
|
pid, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid 'p' field in lsof output: %#v", value)
|
|
}
|
|
cp.PID = uint(pid)
|
|
|
|
case 'n':
|
|
// 'n' is the last field, with '-F cn'
|
|
// format examples:
|
|
// "192.168.2.111:44013->54.229.241.196:80"
|
|
// "[2003:45:2b57:8900:1869:2947:f942:aba7]:55711->[2a00:1450:4008:c01::11]:443"
|
|
// "*:111" <- a listen
|
|
addresses := strings.SplitN(value, "->", 2)
|
|
if len(addresses) != 2 {
|
|
// That's a listen entry.
|
|
continue
|
|
}
|
|
res[addresses[0]] = Proc{
|
|
Name: cp.Name,
|
|
PID: cp.PID,
|
|
}
|
|
|
|
case 'c':
|
|
cp.Name = value
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unexpected lsof field: %c in %#v", field, value)
|
|
}
|
|
}
|
|
|
|
return res, nil
|
|
}
|