-
Notifications
You must be signed in to change notification settings - Fork 0
/
info_process.go
171 lines (160 loc) · 4.75 KB
/
info_process.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package system
import (
"context"
"fmt"
"os"
"strings"
"github.com/admpub/log"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/process"
"github.com/webx-top/com"
)
type Process struct {
Name string `json:"name"`
Pid int32 `json:"pid"`
Ppid int32 `json:"ppid"`
CPUPercent float64 `json:"cpuPercent"`
MemPercent float32 `json:"memPercent"`
MemUsed uint64 `json:"memUsed"`
//Running bool `json:"running"`
CreateTime string `json:"createTime"`
created int64
Exe string `json:"exe"`
Cmdline string `json:"cmdline"`
Cwd string `json:"cwd"`
Status []string `json:"status"`
Username string `json:"username"`
NumThreads int32 `json:"numThreads"`
NumFDs int32 `json:"numFDs"`
}
func IsNotImplemented(err error) bool {
if err == nil {
return false
}
return os.IsNotExist(err) ||
err.Error() == `not implemented yet` ||
strings.HasSuffix(err.Error(), `no such file or directory`)
}
func (p *Process) Parse(ctx context.Context, proc *process.Process) (*Process, error) {
var err error
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf(`%v`, e)
}
}()
p.Pid = proc.Pid
p.CPUPercent, err = proc.CPUPercentWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.CPUPercent: %w`, err)
log.Warn(err.Error())
}
//p.Running, err = proc.IsRunningWithContext(ctx)
p.created, err = proc.CreateTimeWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.CreateTime: %w`, err)
log.Warn(err.Error())
}
if p.created > 0 {
p.CreateTime = com.DateFormat(`Y-m-d H:i:s`, p.created/1000)
}
p.MemPercent, err = p.MemoryPercentWithContext(ctx, proc)
if err != nil {
log.Warn(err.Error())
}
p.Ppid, err = proc.PpidWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.Ppid: %w`, err)
log.Warn(err.Error())
}
p.Name, err = proc.NameWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.Name: %w`, err)
log.Warn(err.Error())
}
p.Exe, err = proc.ExeWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.Exe: %w`, err)
log.Warn(err.Error())
}
p.Cmdline, err = proc.CmdlineWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.Cmdline: %w`, err)
log.Warn(err.Error())
}
p.Cwd, err = proc.CwdWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.Cwd: %w`, err)
log.Warn(err.Error())
}
p.Status, err = proc.StatusWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.Status: %w`, err)
log.Warn(err.Error())
}
p.Username, err = proc.UsernameWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.Username: %w`, err)
log.Warn(err.Error())
}
p.NumThreads, err = proc.NumThreadsWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.NumThreads: %w`, err)
log.Warn(err.Error())
}
p.NumFDs, err = proc.NumFDsWithContext(ctx)
if err != nil && !IsNotImplemented(err) {
err = fmt.Errorf(`failed to parse proc.NumFDs: %w`, err)
log.Warn(err.Error())
}
return p, nil
}
type kMachineMemory string
var ctxKeyMachineMemory kMachineMemory = `system.machineMemory`
func (p *Process) MemoryPercentWithContext(ctx context.Context, proc *process.Process) (float32, error) {
var err error
machineMemory, ok := ctx.Value(ctxKeyMachineMemory).(*mem.VirtualMemoryStat)
if !ok {
machineMemory, err = mem.VirtualMemoryWithContext(ctx)
if err != nil {
return 0, fmt.Errorf(`failed to parse mem.VirtualMemory: %w`, err)
}
ctx = context.WithValue(ctx, ctxKeyMachineMemory, machineMemory)
}
total := machineMemory.Total
processMemory, err := proc.MemoryInfoWithContext(ctx)
if err != nil {
return 0, fmt.Errorf(`failed to parse proc.MemoryInfo: %w`, err)
}
used := processMemory.RSS
p.MemUsed = used // set
if total == 0 {
return 0, nil
}
return (100 * float32(used) / float32(total)), nil
}
func ProcessList(ctx context.Context) ([]*Process, error) {
var err error
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf(`%v`, e)
}
}()
var list []*process.Process
list, err = process.ProcessesWithContext(ctx)
if err != nil {
return nil, fmt.Errorf(`failed to execute process.Processes: %w`, err)
}
processes := make([]*Process, len(list))
exec := func(idx int, proc *process.Process) (err error) {
p := &Process{}
processes[idx], err = p.Parse(ctx, proc)
return
}
for idx, proc := range list {
err = exec(idx, proc)
if err != nil {
log.Warn(err.Error())
}
}
return processes, err
}