summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2017-01-26 00:29:07 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2017-01-26 00:29:07 -0500
commit415dda2945f5d31057b95bc343f7cda210b0c17b (patch)
tree750cba7bcdabd66099866bf2947a9c3af9531631
parentfbc8a95ef9827ca785d43f50b0f8c0a5e390c1dc (diff)
add cgswap
-rw-r--r--.gitignore1
-rw-r--r--Makefile1
-rw-r--r--cgswap.go97
3 files changed, 99 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e1a11d6..542d8a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*~
batterymon
+cgswap
chardiff
chardiff_pre
chardiff_post
diff --git a/Makefile b/Makefile
index 34bfc9d..945b903 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ GOBUILD = go build
BINFILES = \
batterymon \
+ cgswap \
chardiff \
chardiff_pre \
chardiff_post \
diff --git a/cgswap.go b/cgswap.go
new file mode 100644
index 0000000..3491f17
--- /dev/null
+++ b/cgswap.go
@@ -0,0 +1,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