From ff66abefcb6d81526a42985437a9bfd852d64100 Mon Sep 17 00:00:00 2001 From: codeskyblue Date: Thu, 1 Sep 2016 14:04:36 +0800 Subject: [PATCH] add reload support --- README.md | 2 +- gosuv.go | 32 ++++++++++++++++++++++++++++---- res/index.html | 3 +++ res/js/index.js | 13 +++++++++++++ web.go | 42 +++++++++++++++++++++++++++++++----------- 5 files changed, 76 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index baf21a4..848f310 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Features * [x] Realtime log view * [x] Web control page - * [x] Start, Stop, Tail + * [x] Start, Stop, Tail, Reload * [x] Add program support * [ ] Edit support * [ ] Delete support diff --git a/gosuv.go b/gosuv.go index fec4c0c..462709c 100644 --- a/gosuv.go +++ b/gosuv.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" "net/http" "os" "os/exec" @@ -14,6 +13,7 @@ import ( "github.com/equinox-io/equinox" "github.com/goji/httpauth" + "github.com/qiniu/log" "github.com/urfave/cli" ) @@ -84,7 +84,7 @@ func actionStartServer(c *cli.Context) error { addr := cfg.Server.Addr if c.Bool("foreground") { - fmt.Println("added serv: ", addr) + log.Printf("server listen on %v", addr) log.Fatal(http.ListenAndServe(addr, nil)) } else { if checkServerStatus() == nil { @@ -92,7 +92,7 @@ func actionStartServer(c *cli.Context) error { return nil } logPath := filepath.Join(defaultConfigDir, "gosuv.log") - logFd, err := os.Create(logPath) + logFd, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { log.Fatalf("create file %s failed: %v", logPath, err) } @@ -153,7 +153,26 @@ func actionShutdown(c *cli.Context) error { if restart { log.Fatal("Restart not implemented.") } - resp, err := http.Get(cfg.Client.ServerURL + "/api/shutdown") + resp, err := http.Post(cfg.Client.ServerURL+"/api/shutdown", "application/x-www-form-urlencoded", nil) + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal(err) + } + var ret JSONResponse + err = json.Unmarshal(body, &ret) + if err != nil { + log.Fatal(err) + } + fmt.Println(ret.Value) + return nil +} + +func actionReload(c *cli.Context) error { + resp, err := http.Post(cfg.Client.ServerURL+"/api/reload", "application/x-www-form-urlencoded", nil) if err != nil { log.Fatal(err) } @@ -240,6 +259,11 @@ func main() { Usage: "Show program status", Action: actionStatus, }, + { + Name: "reload", + Usage: "Reload config file", + Action: actionReload, + }, { Name: "shutdown", Usage: "Shutdown server", diff --git a/res/index.html b/res/index.html index 24c5f43..b9b8760 100644 --- a/res/index.html +++ b/res/index.html @@ -51,6 +51,9 @@ + diff --git a/res/js/index.js b/res/js/index.js index d5753dc..df5e9ab 100644 --- a/res/js/index.js +++ b/res/js/index.js @@ -95,6 +95,19 @@ var vm = new Vue({ } }); }, + reload: function() { + $.ajax({ + url: "/api/reload", + method: "POST", + success: function(data) { + if (data.status == 0) { + alert("reload success"); + } else { + alert(data.value); + } + } + }); + }, test: function() { console.log("test"); }, diff --git a/web.go b/web.go index aa75cf4..1e5ae05 100644 --- a/web.go +++ b/web.go @@ -105,6 +105,7 @@ func (s *Supervisor) addOrUpdateProgram(pg Program) error { newProc := s.newProcess(pg) s.procMap[pg.Name] = newProc + *s.pgMap[pg.Name] = pg // update origin if isRunning { newProc.Operate(StartEvent) } @@ -114,9 +115,8 @@ func (s *Supervisor) addOrUpdateProgram(pg Program) error { s.pgs = append(s.pgs, &pg) s.pgMap[pg.Name] = &pg s.procMap[pg.Name] = s.newProcess(pg) - // log.Println("Add:", pg.Name) } - return nil // s.saveDB() + return nil } // Check @@ -142,6 +142,8 @@ func (s *Supervisor) readConfigFromDB() (pgs []Program, err error) { } func (s *Supervisor) loadDB() error { + s.mu.Lock() + defer s.mu.Unlock() pgs, err := s.readConfigFromDB() if err != nil { return err @@ -158,19 +160,17 @@ func (s *Supervisor) loadDB() error { continue } name := pg.Name - s.procMap[name].Operate(StopEvent) + log.Printf("stop before delete program: %s", name) + s.stopAndWait(name) delete(s.procMap, name) delete(s.pgMap, name) } - // update programs (because of delete) - s.pgs = make([]*Program, 0, len(s.pgMap)) - for _, pg := range s.pgMap { - s.pgs = append(s.pgs, pg) - } return nil } func (s *Supervisor) saveDB() error { + s.mu.Lock() + defer s.mu.Unlock() data, err := yaml.Marshal(s.pgs) if err != nil { return err @@ -237,6 +237,22 @@ func (s *Supervisor) hShutdown(w http.ResponseWriter, r *http.Request) { }() } +func (s *Supervisor) hReload(w http.ResponseWriter, r *http.Request) { + err := s.loadDB() + log.Println("reload config file") + if err == nil { + s.renderJSON(w, JSONResponse{ + Status: 0, + Value: "load config success", + }) + } else { + s.renderJSON(w, JSONResponse{ + Status: 1, + Value: err.Error(), + }) + } +} + func (s *Supervisor) hGetProgram(w http.ResponseWriter, r *http.Request) { procs := make([]*Process, 0, len(s.pgs)) for _, pg := range s.pgs { @@ -394,7 +410,7 @@ func (s *Supervisor) Close() { for _, proc := range s.procMap { s.stopAndWait(proc.Name) } - fmt.Println("Supervisor closed") + log.Println("server closed") } func (s *Supervisor) catchExitSignal() { @@ -406,7 +422,7 @@ func (s *Supervisor) catchExitSignal() { log.Println("Receive SIGHUP, just ignore") continue } - fmt.Printf("Got signal: %v, stopping all running process\n", sig) + log.Printf("Got signal: %v, stopping all running process\n", sig) s.Close() break } @@ -430,12 +446,16 @@ func newSupervisorHandler() (hdlr http.Handler, err error) { r := mux.NewRouter() r.HandleFunc("/", suv.hIndex) r.HandleFunc("/settings/{name}", suv.hSetting) + r.HandleFunc("/api/status", suv.hStatus) - r.HandleFunc("/api/shutdown", suv.hShutdown) + r.HandleFunc("/api/shutdown", suv.hShutdown).Methods("POST") + r.HandleFunc("/api/reload", suv.hReload).Methods("POST") + r.HandleFunc("/api/programs", suv.hGetProgram).Methods("GET") r.HandleFunc("/api/programs", suv.hAddProgram).Methods("POST") r.HandleFunc("/api/programs/{name}/start", suv.hStartProgram).Methods("POST") r.HandleFunc("/api/programs/{name}/stop", suv.hStopProgram).Methods("POST") + r.HandleFunc("/ws/events", suv.wsEvents) r.HandleFunc("/ws/logs/{name}", suv.wsLog)