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
|
package main
import (
"sync"
"fmt"
"os"
"bufio"
"strings"
"strconv"
)
func handleErr(err error) {
if err != nil {
panic(err)
}
}
type pidinfo struct {
VmSwap int
Cgroup string
}
func in_array(needle string, haystack []string) bool {
for _, straw := range haystack {
if needle == straw {
return true
}
}
return false
}
func main() {
dir, err := os.Open("/proc")
handleErr(err)
fileinfos, err := dir.Readdir(-1)
handleErr(err)
ch := make(chan pidinfo)
dat := make(map[string]int)
var consumers sync.WaitGroup
consumers.Add(1)
go func() {
for info := range ch {
cur, _ := dat[info.Cgroup]
dat[info.Cgroup] = cur + info.VmSwap
}
consumers.Done()
}()
var producers sync.WaitGroup
for _, fileinfo := range fileinfos {
if pid, err := strconv.Atoi(fileinfo.Name()); fileinfo.IsDir() && err == nil {
producers.Add(1)
go func(pid int) {
defer producers.Done()
statusFile, err := os.Open(fmt.Sprintf("/proc/%d/status", pid))
if err != nil {
return
}
cgroupFile, err := os.Open(fmt.Sprintf("/proc/%d/cgroup", pid))
buf := bufio.NewScanner(statusFile)
for buf.Scan() {
line := buf.Text()
if strings.HasPrefix(line, "VmSwap:") {
swap, err := strconv.Atoi(strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(line, "VmSwap:"), "kB")))
if err != nil || swap == 0 {
return
}
buf := bufio.NewScanner(cgroupFile)
for buf.Scan() {
parts := strings.SplitN(buf.Text(), ":", 3)
if len(parts) != 3 {
continue
}
heir := parts[0]
controllers := strings.Split(parts[1], ",")
cgroup := parts[2]
if heir == "0" || in_array("name=systemd", controllers) {
ch <- pidinfo{VmSwap: swap, Cgroup: cgroup}
return
}
}
return
}
}
}(pid)
}
}
producers.Wait()
close(ch)
consumers.Wait()
for cgroup, vmswap := range dat {
fmt.Println(vmswap, "kB", cgroup)
}
}
// grep VmSwap /proc/*/status|sed -rn 's|^/proc/([0-9]+)/status:VmSwap:\s*(\S+ \S+)$|\2 \1|p'|while read -r kb _ pid; do echo "$kb $(systemctl status "$pid"|head -n1|awk '{print $2}')"; done
|