bustle/cmd/bustled/main.go

112 lines
2.3 KiB
Go
Raw Normal View History

2020-06-12 22:25:29 +00:00
package main
import (
2020-06-18 21:36:07 +00:00
"bufio"
"bytes"
2020-06-12 22:25:29 +00:00
"fmt"
"log"
"os"
2020-06-18 21:36:07 +00:00
"os/exec"
"path/filepath"
"strings"
2020-06-12 22:25:29 +00:00
"github.com/fsnotify/fsnotify"
)
2020-06-18 21:36:07 +00:00
// TODO flesh out event handling with an eye towards eventual sampling
2020-06-12 22:25:29 +00:00
func initHomeWatcher() (*fsnotify.Watcher, error) {
2020-06-18 21:36:07 +00:00
fmt.Fprintf(os.Stderr, "setting up home watcher...\n")
2020-06-12 22:25:29 +00:00
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
2020-06-18 21:36:07 +00:00
out, err := exec.Command("sh", "-c", "stats | jq .active_users[] | tr -d '\"'").Output()
if err != nil {
return nil, fmt.Errorf("failed to call and process stats: %w", err)
}
2020-06-12 22:25:29 +00:00
2020-06-18 21:36:07 +00:00
scanner := bufio.NewScanner(bytes.NewReader(out))
for scanner.Scan() {
username := strings.TrimSpace(scanner.Text())
home := filepath.Join("/home", username)
addHome(watcher, home)
2020-06-12 22:25:29 +00:00
}
2020-06-18 21:36:07 +00:00
2020-06-12 22:25:29 +00:00
return watcher, nil
}
2020-06-18 21:36:07 +00:00
func addHome(watcher *fsnotify.Watcher, homePath string) error {
fileCount := 0
filepath.Walk(homePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
}
if info.IsDir() && strings.HasPrefix(info.Name(), ".") {
return filepath.SkipDir
}
fileCount++
if info.Mode()&os.ModeSymlink != 0 {
return nil
}
err = watcher.Add(path)
if err != nil && err.Error() != "permission denied" && err.Error() != "no such file or directory" {
fmt.Printf("%#v\n", err)
fmt.Println("Died at ", fileCount)
fmt.Printf("%#v\n", info)
panic(err.Error())
} else {
fmt.Fprintf(os.Stderr, "watching %s\n", path)
}
return nil
})
return nil
}
func watchHomes(watcher *fsnotify.Watcher) {
fmt.Fprintf(os.Stderr, "starting poll\n")
2020-06-12 22:25:29 +00:00
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("event:", event)
if event.Op&fsnotify.Write == fsnotify.Write {
log.Println("modified file:", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("error:", err)
}
}
}
func cli(args []string) int {
2020-06-18 21:36:07 +00:00
fmt.Fprintf(os.Stderr, "starting\n")
2020-06-12 22:25:29 +00:00
watcher, err := initHomeWatcher()
2020-06-18 21:36:07 +00:00
fmt.Fprintf(os.Stderr, "watcher initialized\n")
2020-06-12 22:25:29 +00:00
if err != nil {
2020-06-18 21:36:07 +00:00
fmt.Fprintf(os.Stderr, "failed to create watcher: %w\n", err)
2020-06-12 22:25:29 +00:00
return 1
}
defer watcher.Close()
// TODO have an event bus to write to
// TODO what is this done for do i need this done
done := make(chan bool)
2020-06-18 21:36:07 +00:00
go watchHomes(watcher)
2020-06-12 22:25:29 +00:00
<-done
return 0
}
func main() {
os.Exit(cli(os.Args))
}