This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
forked from alicebob/procspy
-
Notifications
You must be signed in to change notification settings - Fork 14
/
lsof.go
77 lines (68 loc) · 1.63 KB
/
lsof.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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 seperated, 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
}