diff --git a/README.md b/README.md index 408d825..582799d 100644 --- a/README.md +++ b/README.md @@ -67,11 +67,16 @@ After you installed gosuv, the first thing is to start server. gosuv start-server ``` -Show server status +Basic operations ```sh $ gosuv status -Server is running +PROGRAM NAME STATUS +test running +test_again stopped + +$ gosuv stop test +$ gosuv start test ``` Open web to see the manager page. And follow the gif to add a program to gosuv. diff --git a/cmds.go b/cmds.go index 9c1f445..edf36ca 100644 --- a/cmds.go +++ b/cmds.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "github.com/franela/goreq" "github.com/goji/httpauth" "github.com/urfave/cli" ) @@ -83,11 +84,68 @@ func actionStartServer(c *cli.Context) error { } func actionStatus(c *cli.Context) error { - err := checkServerStatus() + res, err := goreq.Request{ + Uri: cfg.Client.ServerURL + "/api/programs", + }.Do() if err != nil { - log.Fatal(err) + return err + } + var programs = make([]struct { + Program Program `json:"program"` + Status string `json:"status"` + }, 0) + if err := res.Body.FromJsonTo(&programs); err != nil { + return err + } + format := "%-23s\t%-8s\n" + fmt.Printf(format, "PROGRAM NAME", "STATUS") + for _, p := range programs { + fmt.Printf(format, p.Program.Name, p.Status) + } + return nil +} + +// cmd: +func programOperate(cmd, name string) (err error, success bool) { + res, err := goreq.Request{ + Method: "POST", + Uri: cfg.Client.ServerURL + "/api/programs/" + name + "/" + cmd, + }.Do() + if err != nil { + return + } + var v = struct { + Status int `json:"status"` + }{} + if err = res.Body.FromJsonTo(&v); err != nil { + return + } + success = v.Status == 0 + return +} + +func actionStart(c *cli.Context) (err error) { + name := c.Args().First() + err, success := programOperate("start", name) + if err != nil { + return + } + if success { + fmt.Println("Started") } else { - log.Println("Server is running, OK.") + fmt.Println("Start failed") + } + return nil +} + +func actionStop(c *cli.Context) (err error) { + name := c.Args().First() + err, success := programOperate("stop", name) + if err != nil { + return + } + if !success { + fmt.Println("Stop failed") } return nil } diff --git a/gosuv.go b/gosuv.go index 3652e7d..1791511 100644 --- a/gosuv.go +++ b/gosuv.go @@ -141,6 +141,16 @@ func main() { Usage: "Show program status", Action: actionStatus, }, + { + Name: "start", + Usage: "Start program", + Action: actionStart, + }, + { + Name: "stop", + Usage: "Stop program", + Action: actionStop, + }, { Name: "reload", Usage: "Reload config file", diff --git a/sigchld_unix.go b/sigchld_unix.go index 65ed255..7d910a1 100644 --- a/sigchld_unix.go +++ b/sigchld_unix.go @@ -3,6 +3,7 @@ package main import ( + "log" "os" "os/signal" "syscall" @@ -23,6 +24,18 @@ func watchChildSignal() { } func reapChildren() { - var wstatus syscall.WaitStatus - syscall.Wait4(-1, &wstatus, syscall.WNOHANG, nil) + for { + var wstatus syscall.WaitStatus + wpid, err := syscall.Wait4(-1, &wstatus, syscall.WNOHANG, nil) + if err != nil { + log.Printf("syscall.Wait4 call failed: %v", err) + break + } + + if wpid != 0 { + log.Printf("reap dead child: %d, wstatus: %#08x", wpid, wstatus) + } else { + break + } + } }