-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathprocess_linux.go
More file actions
91 lines (76 loc) · 1.61 KB
/
process_linux.go
File metadata and controls
91 lines (76 loc) · 1.61 KB
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//go:build linux
package gons
import (
"errors"
"os"
"path/filepath"
"regexp"
"strconv"
"syscall"
)
const (
defaultProcFsRoot = "/proc"
)
var (
processDirectoryRegex = regexp.MustCompile(`\d+`)
fdSocketInodeRegex = regexp.MustCompile(`socket\:\[(\d+)\]`)
)
// RelateProcess relate socket and process.
func RelateProcess(socket *Socket, options ...OptionSet) error {
// inode
if len(socket.Raw.fields) < 10 {
return errors.New("process: can't get inode")
}
// option set
o := new(Option)
for _, fn := range options {
fn(o)
}
// find process
find := false
inode := socket.Raw.fields[9]
if o.procFsRoot == "" {
o.procFsRoot = defaultProcFsRoot
}
dirs, err := os.ReadDir(o.procFsRoot)
if err != nil {
return err
}
for _, pd := range dirs {
if pd.IsDir() && processDirectoryRegex.MatchString(pd.Name()) {
fds, err := os.ReadDir(filepath.Join(o.procFsRoot, pd.Name(), "fd"))
if err != nil {
continue
}
for _, fd := range fds {
link := make([]byte, 512)
_, err := syscall.Readlink(filepath.Join(o.procFsRoot, pd.Name(), "fd", fd.Name()), link)
if err != nil {
continue
}
groups := fdSocketInodeRegex.FindSubmatch(link)
if len(groups) != 2 {
continue
}
if string(groups[1]) == inode {
pid, err := strconv.Atoi(pd.Name())
if err != nil {
continue
}
cmdline, err := os.ReadFile(filepath.Join(o.procFsRoot, pd.Name(), "cmdline"))
if err != nil {
continue
}
socket.Pid = pid
socket.ProgramName = string(cmdline)
find = true
break
}
}
if find {
break
}
}
}
return nil
}