]> Sergey Matveev's repositories - godwmstat.git/blob - main.go
45192b23d7862222f747bfe460a4b06315119ab5
[godwmstat.git] / main.go
1 package main
2
3 import (
4         "bufio"
5         "flag"
6         "fmt"
7         "log"
8         "os"
9         "os/exec"
10         "strconv"
11         "strings"
12         "time"
13
14         "github.com/dustin/go-humanize"
15 )
16
17 var (
18         MyPID string = strconv.Itoa(os.Getpid())
19         CPU   string = "?"
20         Freq  string = "?"
21         Mem   string = "?"
22         ARC   string = "?"
23         Swap  string = "?"
24         Flags string = "?"
25         IOs   string = "?"
26         Net   string = "?"
27 )
28
29 func piper(c chan []string, name string, args ...string) error {
30         cmd := exec.Command(name, args...)
31         r, err := cmd.StdoutPipe()
32         if err != nil {
33                 return err
34         }
35         err = cmd.Start()
36         if err != nil {
37                 return err
38         }
39         scanner := bufio.NewScanner(r)
40         for scanner.Scan() {
41                 cols := strings.Fields(scanner.Text())
42                 if len(cols) > 0 {
43                         c <- cols
44                 }
45         }
46         if err = scanner.Err(); err != nil {
47                 cmd.Process.Kill()
48                 cmd.Wait()
49                 return err
50         }
51         return nil
52 }
53
54 func bg(cmd string, args ...string) chan []string {
55         c := make(chan []string)
56         go func() {
57                 for {
58                         err := piper(c, cmd, args...)
59                         if err != nil {
60                                 log.Println("error:", cmd, ":", err)
61                         }
62                         time.Sleep(time.Second)
63                 }
64         }()
65         return c
66 }
67
68 func top() {
69         for cols := range bg("top", "-b", "-d", "infinity", "-p", MyPID, "-s", "5", "infinity") {
70                 switch cols[0] {
71                 case "CPU:":
72                         CPU = strings.ReplaceAll(fmt.Sprintf(
73                                 "%s sys:%s int:%s n:%s",
74                                 cols[1], cols[5], cols[7], cols[3],
75                         ), "%", "")
76                 case "Mem:":
77                         Mem = strings.ReplaceAll(strings.Join(cols[1:], " "), ",", "")
78                 case "ARC:":
79                         ARC = cols[1]
80                 case "Swap:":
81                         if len(cols) >= 5 && cols[4] == "Used," {
82                                 Swap = cols[3] + " Swap "
83                         } else {
84                                 Swap = ""
85                         }
86                 }
87         }
88 }
89
90 func iostat() {
91         var stats []string
92         for cols := range bg("iostat", "-d", "-w", "1", "-x") {
93                 if cols[0] == "device" {
94                         IOs = strings.Join(stats, " ")
95                         stats = nil
96                         continue
97                 }
98                 if len(cols) < 4 || (cols[1] == "0" && cols[2] == "0") {
99                         continue
100                 }
101                 stats = append(stats, fmt.Sprintf("%s:%s/%s", cols[0], cols[1], cols[2]))
102         }
103 }
104
105 func netstat() {
106         for cols := range bg("netstat", "-I", "bridge0", "-n", "1") {
107                 if _, err := strconv.Atoi(cols[0]); err != nil {
108                         continue
109                 }
110                 ibps, err := strconv.Atoi(cols[3])
111                 if err != nil {
112                         continue
113                 }
114                 obps, err := strconv.Atoi(cols[6])
115                 if err != nil {
116                         continue
117                 }
118                 Net = fmt.Sprintf(
119                         "%s/%s %s / %s",
120                         cols[0], cols[4],
121                         humanize.IBytes(uint64(ibps)),
122                         humanize.IBytes(uint64(obps)),
123                 )
124         }
125 }
126
127 func freq() {
128         for cols := range bg("sysctl", "-n", "dev.cpu.0.freq") {
129                 if strings.HasSuffix(cols[0], "01") {
130                         Freq = "TB"
131                 } else {
132                         raw, err := strconv.Atoi(cols[0])
133                         if err != nil {
134                                 continue
135                         }
136                         Freq = fmt.Sprintf("%.1fG", float64(raw)/1000)
137                 }
138         }
139 }
140
141 func flagfiles() {
142         ents, err := os.ReadDir("/tmp/stargrave-flags")
143         if err != nil {
144                 log.Println(err)
145                 return
146         }
147         fs := make([]string, 0, len(ents))
148         for _, ent := range ents {
149                 fs = append(fs, ent.Name())
150         }
151         Flags = strings.Join(fs, " ")
152 }
153
154 func main() {
155         xsetroot := flag.Bool("xsetroot", false, "Call xsetroot")
156         flag.Parse()
157         go func() {
158                 for {
159                         flagfiles()
160                         time.Sleep(20 * time.Second)
161                 }
162         }()
163         go top()
164         go freq()
165         go iostat()
166         go netstat()
167         var now time.Time
168         var status string
169         var cmd *exec.Cmd
170         for {
171                 now = time.Now()
172                 status = fmt.Sprintf(
173                         "[%s]  [%s]  [%s %s]  [%s%s %s ARC]  [%s] %s",
174                         IOs, Net, CPU, Freq, Swap, Mem, ARC, Flags,
175                         now.Format("2006-01-02 15:04:05"),
176                 )
177                 if *xsetroot {
178                         cmd = exec.Command("xsetroot", "-name", status)
179                         cmd.Run()
180                 } else {
181                         fmt.Println(status)
182                 }
183                 time.Sleep(time.Second)
184         }
185 }