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)