Initial commit
authorSergey Matveev <stargrave@stargrave.org>
Tue, 24 Aug 2021 10:49:19 +0000 (13:49 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Tue, 24 Aug 2021 10:49:19 +0000 (13:49 +0300)
go.mod [new file with mode: 0644]
main.go [new file with mode: 0644]

diff --git a/go.mod b/go.mod
new file mode 100644 (file)
index 0000000..de0386d
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module go.stargrave.org/godwmstat
+
+go 1.17
diff --git a/main.go b/main.go
new file mode 100644 (file)
index 0000000..8c85756
--- /dev/null
+++ b/main.go
@@ -0,0 +1,163 @@
+package main
+
+import (
+       "bufio"
+       "flag"
+       "fmt"
+       "log"
+       "os"
+       "os/exec"
+       "strconv"
+       "strings"
+       "time"
+)
+
+var (
+       MyPID string = strconv.Itoa(os.Getpid())
+       CPU   string = "?"
+       Mem   string = "?"
+       ARC   string = "?"
+       Swap  string = "?"
+       Flags string = "?"
+       IOs   string = "?"
+       Net   string = "?"
+       N     string = "?"
+)
+
+func piper(c chan []string, name string, args ...string) error {
+       cmd := exec.Command(name, args...)
+       r, err := cmd.StdoutPipe()
+       if err != nil {
+               return err
+       }
+       err = cmd.Start()
+       if err != nil {
+               return err
+       }
+       scanner := bufio.NewScanner(r)
+       for scanner.Scan() {
+               cols := strings.Fields(scanner.Text())
+               if len(cols) > 0 {
+                       c <- cols
+               }
+       }
+       if err = scanner.Err(); err != nil {
+               cmd.Process.Kill()
+               cmd.Wait()
+               return err
+       }
+       return nil
+}
+
+func bg(cmd string, args ...string) chan []string {
+       c := make(chan []string)
+       go func() {
+               for {
+                       err := piper(c, cmd, args...)
+                       if err != nil {
+                               log.Println("error:", cmd, ":", err)
+                       }
+                       time.Sleep(time.Second)
+               }
+       }()
+       return c
+}
+
+func top() {
+       for cols := range bg("top", "-b", "-d", "infinity", "-p", MyPID, "-s", "5", "infinity") {
+               switch cols[0] {
+               case "CPU:":
+                       CPU = strings.ReplaceAll(
+                               strings.Join([]string{cols[1], cols[5], cols[7]}, " "),
+                               "%", "",
+                       )
+               case "Mem:":
+                       Mem = strings.ReplaceAll(strings.Join(cols[1:], " "), ",", "")
+               case "ARC:":
+                       ARC = cols[1]
+               case "Swap:":
+                       if cols[4] == "Used," {
+                               Swap = cols[3] + " "
+                       } else {
+                               Swap = ""
+                       }
+               }
+       }
+}
+
+func iostat(devs ...string) {
+       stats := make([]string, len(devs)*4)
+       for i := 0; i < len(devs); i++ {
+               stats[i*4+1] = "/"
+               stats[i*4+3] = " "
+       }
+       stats = stats[:len(stats)-1]
+       for cols := range bg("iostat", append([]string{"-d", "-w", N, "-x"}, devs...)...) {
+               for i, dev := range devs {
+                       if cols[0] == dev {
+                               stats[i*4+0] = cols[1]
+                               stats[i*4+2] = cols[2]
+                               IOs = strings.Join(stats, "")
+                       }
+               }
+       }
+}
+
+func netstat() {
+       stats := []string{"0", "0"}
+       for cols := range bg("netstat", "-n", N) {
+               if _, err := strconv.Atoi(cols[0]); err == nil {
+                       stats[0] = cols[0]
+                       stats[1] = cols[4]
+                       Net = strings.Join(stats, "/")
+               }
+       }
+}
+
+func flagfiles() {
+       ents, err := os.ReadDir("/tmp/stargrave-flags")
+       if err != nil {
+               log.Println(err)
+               return
+       }
+       fs := make([]string, 0, len(ents))
+       for _, ent := range ents {
+               fs = append(fs, ent.Name())
+       }
+       Flags = strings.Join(fs, " ")
+}
+
+func main() {
+       xsetroot := flag.Bool("xsetroot", false, "Call xsetroot")
+       iodevs := flag.String("iodevs", "ada0 ada1", "iostat devices")
+       refresh := flag.Uint("refresh", 2, "Refresh interval")
+       flag.Parse()
+       N = strconv.Itoa(int(*refresh))
+       go func() {
+               for {
+                       flagfiles()
+                       time.Sleep(20 * time.Second)
+               }
+       }()
+       go top()
+       go iostat(strings.Split(*iodevs, " ")...)
+       go netstat()
+       var now time.Time
+       var status string
+       var cmd *exec.Cmd
+       for {
+               now = time.Now()
+               status = fmt.Sprintf(
+                       "[IO %s]  [Net %s]  [CPU %s]  [%sMem %s ARC %s]  [%s] %s",
+                       IOs, Net, CPU, Swap, Mem, ARC, Flags,
+                       now.Format("2006-01-02 15:04:05"),
+               )
+               if *xsetroot {
+                       cmd = exec.Command("xsetroot", "-name", status)
+                       cmd.Run()
+               } else {
+                       fmt.Println(status)
+               }
+               time.Sleep(time.Duration(*refresh) * time.Second)
+       }
+}