From 2f6f5d32a340664f3500fd8929d7c9368c91a1f4 Mon Sep 17 00:00:00 2001 From: Simon Let Date: Wed, 15 May 2019 18:57:26 +0200 Subject: [PATCH] add config, add pidfile, prevent daemon from runnig more than once --- Makefile | 10 ++-- collect/resh-collect.go | 19 +++++-- common/resh-common.go | 3 ++ config.toml | 1 + daemon/resh-daemon.go | 114 ++++++++++++++++++++++++++++++++++++++-- 5 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 config.toml diff --git a/Makefile b/Makefile index da0dbd6..018fb00 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,9 @@ SHELL=/bin/bash build: submodules resh-collect resh-daemon -install: build | $(HOME)/.resh $(HOME)/.resh/bin +install: build | $(HOME)/.resh $(HOME)/.resh/bin $(HOME)/.config/resh cp submodules/bash-preexec/bash-preexec.sh ~/.bash-preexec.sh -f + cp config.toml ~/.config/resh.toml -f cp bashrc.sh ~/.resh/bashrc -f cp resh-* ~/.resh/bin/ -f grep '[[ -f ~/.resh/bashrc ]] && source ~/.resh/bashrc' ~/.bashrc ||\ @@ -23,11 +24,8 @@ resh-collect: collect/resh-collect.go common/resh-common.go go build -o $@ $< -$(HOME)/.resh: - mkdir $(HOME)/.resh - -$(HOME)/.resh/bin: - mkdir $(HOME)/.resh/bin +$(HOME)/.resh $(HOME)/.resh/bin $(HOME)/.config/resh: + mkdir -p $@ .PHONY: submodules build install diff --git a/collect/resh-collect.go b/collect/resh-collect.go index 5bba328..07a4720 100644 --- a/collect/resh-collect.go +++ b/collect/resh-collect.go @@ -5,14 +5,27 @@ import ( "encoding/json" "os" "os/exec" + "os/user" + "path/filepath" "log" "net/http" "strconv" "strings" common "github.com/curusarn/resh/common" + "github.com/BurntSushi/toml" ) func main() { + usr, _ := user.Current() + dir := usr.HomeDir + configPath := filepath.Join(dir, "/.config/resh.toml") + + var config common.Config + if _, err := toml.DecodeFile(configPath, &config); err != nil { + log.Println("Error reading config", err) + return + } + exitCode, err := strconv.Atoi(os.Args[1]) if err != nil { // log this @@ -27,16 +40,16 @@ func main() { Shell: os.Getenv("SHELL"), ExitCode: exitCode, } - sendRecord(rec) + sendRecord(rec, strconv.Itoa(config.Port)) } -func sendRecord(r common.Record) { +func sendRecord(r common.Record, port string) { recJson, err := json.Marshal(r) if err != nil { log.Fatal("1 ", err) } - req, err := http.NewRequest("POST", "http://localhost:8888", + req, err := http.NewRequest("POST", "http://localhost:" + port + "/record", bytes.NewBuffer(recJson)) if err != nil { log.Fatal("2 ", err) diff --git a/common/resh-common.go b/common/resh-common.go index 9a18d47..6e0d2a6 100644 --- a/common/resh-common.go +++ b/common/resh-common.go @@ -9,3 +9,6 @@ type Record struct { Logs []string `json: logs` } +type Config struct { + Port int +} diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..ff81050 --- /dev/null +++ b/config.toml @@ -0,0 +1 @@ +port = 8888 diff --git a/daemon/resh-daemon.go b/daemon/resh-daemon.go index aacba0b..3f7d4b5 100644 --- a/daemon/resh-daemon.go +++ b/daemon/resh-daemon.go @@ -2,14 +2,65 @@ package main import ( "encoding/json" + //"flag" "log" "io/ioutil" + "path/filepath" + "os" + "os/exec" + "os/user" + "strconv" + "strings" + //"syscall" "net/http" common "github.com/curusarn/resh/common" + "github.com/BurntSushi/toml" ) + + func main() { - server() + usr, _ := user.Current() + dir := usr.HomeDir + pidfilePath := filepath.Join(dir, ".resh/resh.pid") + configPath := filepath.Join(dir, "/.config/resh.toml") + + var config common.Config + if _, err := toml.DecodeFile(configPath, &config); err != nil { + log.Println("Error reading config", err) + return + } + res, err := isDaemonRunning(config.Port) + if err != nil { + log.Println("Error while checking if the daemon is runnnig", err) + } + if res { + log.Println("Daemon is already runnnig - exiting!") + return + } + _, err = os.Stat(pidfilePath) + if err == nil { + log.Println("Pidfile exists") + // kill daemon + err = killDaemon(pidfilePath) + if err != nil { + log.Println("Error while killing daemon", err) + } + } + err = ioutil.WriteFile(pidfilePath, []byte(strconv.Itoa(os.Getpid())), 0644) + if err != nil { + log.Fatal("Could not create pidfile", err) + } + server(config.Port) + err = os.Remove(pidfilePath) + if err != nil { + log.Println("Could not delete pidfile", err) + } +} + +func statusHandler(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("OK\n")) + log.Printf("Status OK\n") } func recordHandler(w http.ResponseWriter, r *http.Request) { @@ -25,6 +76,7 @@ func recordHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(jsn, &record) if err != nil { log.Println("Decoding error: ", err) + log.Println("Payload: ", jsn) return } @@ -35,7 +87,61 @@ func recordHandler(w http.ResponseWriter, r *http.Request) { // fmt.Println("exit_code:", r.ExitCode) } -func server() { - http.HandleFunc("/", recordHandler) - http.ListenAndServe(":8888", nil) +func server(port int) { + http.HandleFunc("/status", statusHandler) + http.HandleFunc("/record", recordHandler) + http.ListenAndServe(":" + strconv.Itoa(port) , nil) +} + +func killDaemon(pidfile string) error { + dat, err := ioutil.ReadFile(pidfile) + if err != nil { + log.Println("Reading pid file failed", err) + } + log.Print(string(dat)) + pid, err := strconv.Atoi(strings.TrimSuffix(string(dat), "\n")) + if err != nil { + log.Fatal("Pidfile contents are malformed", err) + } + cmd := exec.Command("kill", strconv.Itoa(pid)) + err = cmd.Run() + if err != nil { + log.Printf("Command finished with error: %v", err) + return err + } + return nil +} + +func isDaemonRunning(port int) (bool, error) { + url := "http://localhost:" + strconv.Itoa(port) + "/status" + resp, err := http.Get(url) + if err != nil { + log.Println("Error while checking daemon status - " + + "it's probably not runnig!", err) + return false, err + } + defer resp.Body.Close() + return true, nil + //body, err := ioutil.ReadAll(resp.Body) + + +// dat, err := ioutil.ReadFile(pidfile) +// if err != nil { +// log.Println("Reading pid file failed", err) +// return false, err +// } +// log.Print(string(dat)) +// pid, err := strconv.ParseInt(string(dat), 10, 64) +// if err != nil { +// log.Fatal(err) +// } +// process, err := os.FindProcess(int(pid)) +// if err != nil { +// log.Printf("Failed to find process: %s\n", err) +// return false, err +// } else { +// err := process.Signal(syscall.Signal(0)) +// log.Printf("process.Signal on pid %d returned: %v\n", pid, err) +// } +// return true, nil }