1 package process
2
3 import (
4 "bytes"
5 "context"
6 "io/ioutil"
7 "os"
8 "strconv"
9 "strings"
10
11 "github.com/shirou/gopsutil/cpu"
12 "github.com/shirou/gopsutil/internal/common"
13 "github.com/shirou/gopsutil/net"
14 )
15
16 type MemoryMapsStat struct {
17 Path string `json:"path"`
18 Rss uint64 `json:"rss"`
19 Size uint64 `json:"size"`
20 Pss uint64 `json:"pss"`
21 SharedClean uint64 `json:"sharedClean"`
22 SharedDirty uint64 `json:"sharedDirty"`
23 PrivateClean uint64 `json:"privateClean"`
24 PrivateDirty uint64 `json:"privateDirty"`
25 Referenced uint64 `json:"referenced"`
26 Anonymous uint64 `json:"anonymous"`
27 Swap uint64 `json:"swap"`
28 }
29
30 type MemoryInfoExStat struct {
31 }
32
33 func pidsWithContext(ctx context.Context) ([]int32, error) {
34 return readPidsFromDir(common.HostProc())
35 }
36
37 func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
38 out := []*Process{}
39
40 pids, err := PidsWithContext(ctx)
41 if err != nil {
42 return out, err
43 }
44
45 for _, pid := range pids {
46 p, err := NewProcessWithContext(ctx, pid)
47 if err != nil {
48 continue
49 }
50 out = append(out, p)
51 }
52
53 return out, nil
54 }
55
56 func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
57 return 0, common.ErrNotImplementedError
58 }
59
60 func (p *Process) NameWithContext(ctx context.Context) (string, error) {
61 return "", common.ErrNotImplementedError
62 }
63
64 func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
65 return 0, common.ErrNotImplementedError
66 }
67
68 func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
69 exe, err := p.fillFromPathAOutWithContext(ctx)
70 if os.IsNotExist(err) {
71 exe, err = p.fillFromExecnameWithContext(ctx)
72 }
73 return exe, err
74 }
75
76 func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
77 return p.fillFromCmdlineWithContext(ctx)
78 }
79
80 func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
81 return p.fillSliceFromCmdlineWithContext(ctx)
82 }
83
84 func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
85 return 0, common.ErrNotImplementedError
86 }
87
88 func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
89 return p.fillFromPathCwdWithContext(ctx)
90 }
91
92 func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
93 return nil, common.ErrNotImplementedError
94 }
95
96 func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
97 return "", common.ErrNotImplementedError
98 }
99
100 func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
101 return false, common.ErrNotImplementedError
102 }
103
104 func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
105 return nil, common.ErrNotImplementedError
106 }
107
108 func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
109 return nil, common.ErrNotImplementedError
110 }
111
112 func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
113 return nil, common.ErrNotImplementedError
114 }
115
116 func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
117 return "", common.ErrNotImplementedError
118 }
119
120 func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
121 return 0, common.ErrNotImplementedError
122 }
123
124 func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
125 return 0, common.ErrNotImplementedError
126 }
127
128 func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
129 return nil, common.ErrNotImplementedError
130 }
131
132 func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
133 return nil, common.ErrNotImplementedError
134 }
135
136 func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
137 return nil, common.ErrNotImplementedError
138 }
139
140 func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
141 return nil, common.ErrNotImplementedError
142 }
143
144 func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
145 _, fnames, err := p.fillFromfdListWithContext(ctx)
146 return int32(len(fnames)), err
147 }
148
149 func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
150 return 0, common.ErrNotImplementedError
151 }
152
153 func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
154 return nil, common.ErrNotImplementedError
155 }
156
157 func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
158 return nil, common.ErrNotImplementedError
159 }
160
161 func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
162 return nil, common.ErrNotImplementedError
163 }
164
165 func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
166 return nil, common.ErrNotImplementedError
167 }
168
169 func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
170 return nil, common.ErrNotImplementedError
171 }
172
173 func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
174 return nil, common.ErrNotImplementedError
175 }
176
177 func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
178 return nil, common.ErrNotImplementedError
179 }
180
181 func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
182 return nil, common.ErrNotImplementedError
183 }
184
185 func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
186 return nil, common.ErrNotImplementedError
187 }
188
189 func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
190 return nil, common.ErrNotImplementedError
191 }
192
193 func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
194 return nil, common.ErrNotImplementedError
195 }
196
197 func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
198 return nil, common.ErrNotImplementedError
199 }
200
201 func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
202 return nil, common.ErrNotImplementedError
203 }
204
205
208
209 func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) {
210 pid := p.Pid
211 statPath := common.HostProc(strconv.Itoa(int(pid)), "fd")
212 d, err := os.Open(statPath)
213 if err != nil {
214 return statPath, []string{}, err
215 }
216 defer d.Close()
217 fnames, err := d.Readdirnames(-1)
218 return statPath, fnames, err
219 }
220
221 func (p *Process) fillFromPathCwdWithContext(ctx context.Context) (string, error) {
222 pid := p.Pid
223 cwdPath := common.HostProc(strconv.Itoa(int(pid)), "path", "cwd")
224 cwd, err := os.Readlink(cwdPath)
225 if err != nil {
226 return "", err
227 }
228 return cwd, nil
229 }
230
231 func (p *Process) fillFromPathAOutWithContext(ctx context.Context) (string, error) {
232 pid := p.Pid
233 cwdPath := common.HostProc(strconv.Itoa(int(pid)), "path", "a.out")
234 exe, err := os.Readlink(cwdPath)
235 if err != nil {
236 return "", err
237 }
238 return exe, nil
239 }
240
241 func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, error) {
242 pid := p.Pid
243 execNamePath := common.HostProc(strconv.Itoa(int(pid)), "execname")
244 exe, err := ioutil.ReadFile(execNamePath)
245 if err != nil {
246 return "", err
247 }
248 return string(exe), nil
249 }
250
251 func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
252 pid := p.Pid
253 cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
254 cmdline, err := ioutil.ReadFile(cmdPath)
255 if err != nil {
256 return "", err
257 }
258 ret := strings.FieldsFunc(string(cmdline), func(r rune) bool {
259 if r == '\u0000' {
260 return true
261 }
262 return false
263 })
264
265 return strings.Join(ret, " "), nil
266 }
267
268 func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
269 pid := p.Pid
270 cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
271 cmdline, err := ioutil.ReadFile(cmdPath)
272 if err != nil {
273 return nil, err
274 }
275 if len(cmdline) == 0 {
276 return nil, nil
277 }
278 if cmdline[len(cmdline)-1] == 0 {
279 cmdline = cmdline[:len(cmdline)-1]
280 }
281 parts := bytes.Split(cmdline, []byte{0})
282 var strParts []string
283 for _, p := range parts {
284 strParts = append(strParts, string(p))
285 }
286
287 return strParts, nil
288 }
289
290 func readPidsFromDir(path string) ([]int32, error) {
291 var ret []int32
292
293 d, err := os.Open(path)
294 if err != nil {
295 return nil, err
296 }
297 defer d.Close()
298
299 fnames, err := d.Readdirnames(-1)
300 if err != nil {
301 return nil, err
302 }
303 for _, fname := range fnames {
304 pid, err := strconv.ParseInt(fname, 10, 32)
305 if err != nil {
306
307 continue
308 }
309 ret = append(ret, int32(pid))
310 }
311
312 return ret, nil
313 }
314
View as plain text