11package service
22
33import (
4+ "bufio"
45 "fmt"
56 "github.com/1Panel-dev/1Panel/agent/app/dto/request"
67 "github.com/1Panel-dev/1Panel/agent/utils/common"
78 "github.com/1Panel-dev/1Panel/agent/utils/websocket"
89 "github.com/shirou/gopsutil/v4/process"
10+ "os"
11+ "strconv"
12+ "strings"
913 "time"
1014)
1115
@@ -103,24 +107,20 @@ func (ps *ProcessService) GetProcessInfoByPID(pid int32) (*websocket.PsProcessDa
103107 data .CmdLine = cmdline
104108 }
105109
106- if memInfo , err := p .MemoryInfo (); err == nil {
107- data .Rss = common .FormatBytes (memInfo .RSS )
108- data .VMS = common .FormatBytes (memInfo .VMS )
109- data .HWM = common .FormatBytes (memInfo .HWM )
110- data .Data = common .FormatBytes (memInfo .Data )
111- data .Stack = common .FormatBytes (memInfo .Stack )
112- data .Locked = common .FormatBytes (memInfo .Locked )
113- data .Swap = common .FormatBytes (memInfo .Swap )
114- data .RssValue = memInfo .RSS
115- } else {
116- data .Rss = "--"
117- data .Data = "--"
118- data .VMS = "--"
119- data .HWM = "--"
120- data .Stack = "--"
121- data .Locked = "--"
122- data .Swap = "--"
123- data .RssValue = 0
110+ if memDetail , err := getMemoryDetail (p .Pid ); err == nil {
111+ data .Rss = common .FormatBytes (memDetail .RSS )
112+ data .VMS = common .FormatBytes (memDetail .VMS )
113+ data .HWM = common .FormatBytes (memDetail .HWM )
114+ data .Data = common .FormatBytes (memDetail .Data )
115+ data .Stack = common .FormatBytes (memDetail .Stack )
116+ data .Locked = common .FormatBytes (memDetail .Locked )
117+ data .Swap = common .FormatBytes (memDetail .Swap )
118+ data .Dirty = common .FormatBytes (memDetail .Dirty )
119+ data .RssValue = memDetail .RSS
120+ data .PSS = common .FormatBytes (memDetail .PSS )
121+ data .USS = common .FormatBytes (memDetail .USS )
122+ data .Shared = common .FormatBytes (memDetail .Shared )
123+ data .Text = common .FormatBytes (memDetail .Text )
124124 }
125125
126126 if envs , err := p .Environ (); err == nil {
@@ -133,3 +133,152 @@ func (ps *ProcessService) GetProcessInfoByPID(pid int32) (*websocket.PsProcessDa
133133
134134 return data , nil
135135}
136+
137+ type MemoryDetail struct {
138+ RSS uint64
139+ VMS uint64
140+ HWM uint64
141+ Data uint64
142+ Stack uint64
143+ Locked uint64
144+ Swap uint64
145+
146+ PSS uint64
147+ USS uint64
148+ Shared uint64
149+ Text uint64
150+ Dirty uint64
151+ }
152+
153+ func getMemoryDetail (pid int32 ) (* MemoryDetail , error ) {
154+ mem := & MemoryDetail {}
155+
156+ if err := readStatus (pid , mem ); err != nil {
157+ return nil , err
158+ }
159+
160+ if err := readSmapsRollup (pid , mem ); err != nil {
161+ if err := readSmaps (pid , mem ); err != nil {
162+ return nil , err
163+ }
164+ }
165+ return mem , nil
166+ }
167+
168+ func readStatus (pid int32 , mem * MemoryDetail ) error {
169+ filePath := fmt .Sprintf ("/proc/%d/status" , pid )
170+ file , err := os .Open (filePath )
171+ if err != nil {
172+ return err
173+ }
174+ defer file .Close ()
175+
176+ scanner := bufio .NewScanner (file )
177+
178+ for scanner .Scan () {
179+ line := scanner .Text ()
180+ fields := strings .Fields (line )
181+ if len (fields ) < 2 {
182+ continue
183+ }
184+
185+ key := strings .TrimSuffix (fields [0 ], ":" )
186+ value , _ := strconv .ParseUint (fields [1 ], 10 , 64 )
187+ value *= 1024
188+
189+ switch key {
190+ case "VmRSS" :
191+ mem .RSS = value
192+ case "VmSize" :
193+ mem .VMS = value
194+ case "VmData" :
195+ mem .Data = value
196+ case "VmSwap" :
197+ mem .Swap = value
198+ case "VmExe" :
199+ mem .Text = value
200+ case "RssShmem" :
201+ mem .Shared = value
202+ case "VmHWM" :
203+ mem .HWM = value
204+ case "VmStk" :
205+ mem .Stack = value
206+ case "VmLck" :
207+ mem .Locked = value
208+ }
209+ }
210+
211+ return scanner .Err ()
212+ }
213+
214+ func readSmapsRollup (pid int32 , mem * MemoryDetail ) error {
215+ filePath := fmt .Sprintf ("/proc/%d/smaps_rollup" , pid )
216+ file , err := os .Open (filePath )
217+ if err != nil {
218+ return err
219+ }
220+ defer file .Close ()
221+
222+ scanner := bufio .NewScanner (file )
223+
224+ for scanner .Scan () {
225+ line := scanner .Text ()
226+ fields := strings .Fields (line )
227+ if len (fields ) < 2 {
228+ continue
229+ }
230+
231+ key := strings .TrimSuffix (fields [0 ], ":" )
232+ value , _ := strconv .ParseUint (fields [1 ], 10 , 64 )
233+ value *= 1024
234+
235+ switch key {
236+ case "Pss" :
237+ mem .PSS = value
238+ case "Private_Clean" , "Private_Dirty" :
239+ mem .USS += value
240+ case "Shared_Clean" , "Shared_Dirty" :
241+ if mem .Shared == 0 {
242+ mem .Shared = value
243+ }
244+ }
245+ }
246+
247+ return scanner .Err ()
248+ }
249+
250+ func readSmaps (pid int32 , mem * MemoryDetail ) error {
251+ filePath := fmt .Sprintf ("/proc/%d/smaps" , pid )
252+ file , err := os .Open (filePath )
253+ if err != nil {
254+ return err
255+ }
256+ defer file .Close ()
257+
258+ scanner := bufio .NewScanner (file )
259+
260+ for scanner .Scan () {
261+ line := scanner .Text ()
262+ fields := strings .Fields (line )
263+ if len (fields ) < 2 {
264+ continue
265+ }
266+
267+ key := strings .TrimSuffix (fields [0 ], ":" )
268+ value , _ := strconv .ParseUint (fields [1 ], 10 , 64 )
269+ value *= 1024
270+
271+ switch key {
272+ case "Pss" :
273+ mem .PSS += value
274+ case "Private_Clean" , "Private_Dirty" :
275+ mem .USS += value
276+ case "Shared_Clean" , "Shared_Dirty" :
277+ if mem .Shared == 0 {
278+ mem .Shared += value
279+ }
280+ }
281+ }
282+
283+ return scanner .Err ()
284+ }
0 commit comments