fix
This commit is contained in:
100
main.go
100
main.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -15,6 +16,12 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ch chan struct{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ch = make(chan struct{})
|
||||||
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
CMD string `json:"cmd"`
|
CMD string `json:"cmd"`
|
||||||
Args []string `json:"args"`
|
Args []string `json:"args"`
|
||||||
@ -31,9 +38,9 @@ func printErr(err error) {
|
|||||||
fmt.Fprintf(os.Stderr, "[qini] Err: %s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "[qini] Err: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func printInfo(info string) {
|
// func printInfo(info string) {
|
||||||
fmt.Fprintf(os.Stderr, "[qini] Inf: %s\n", info)
|
// fmt.Fprintf(os.Stderr, "[qini] Inf: %s\n", info)
|
||||||
}
|
// }
|
||||||
|
|
||||||
var verbose bool
|
var verbose bool
|
||||||
|
|
||||||
@ -60,27 +67,31 @@ func stopAllServices(services []*Service) {
|
|||||||
}
|
}
|
||||||
}(s)
|
}(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loop:
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
for _, s := range services {
|
||||||
|
if s.cmd.Process != nil && s.cmd.ProcessState == nil {
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runServices(services []*Service) int {
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runServices(services []*Service) error {
|
||||||
if len(services) == 0 {
|
if len(services) == 0 {
|
||||||
printInfo("no services in config")
|
return errors.New("no services in config")
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
r *io.PipeReader
|
r *io.PipeReader
|
||||||
w *io.PipeWriter
|
w *io.PipeWriter
|
||||||
|
|
||||||
lock sync.Mutex
|
|
||||||
once sync.Once
|
|
||||||
wg sync.WaitGroup
|
|
||||||
|
|
||||||
exitCode int
|
|
||||||
)
|
)
|
||||||
|
|
||||||
lock.Lock()
|
|
||||||
|
|
||||||
for i, s := range services {
|
for i, s := range services {
|
||||||
s.cmd = exec.Command(s.CMD, s.Args...)
|
s.cmd = exec.Command(s.CMD, s.Args...)
|
||||||
|
|
||||||
@ -103,42 +114,20 @@ func runServices(services []*Service) int {
|
|||||||
s.cmd.Stdout = os.Stdout
|
s.cmd.Stdout = os.Stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Add(1)
|
|
||||||
go func(w *io.PipeWriter) {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if w != nil {
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
once.Do(func() {
|
|
||||||
lock.Lock()
|
|
||||||
defer lock.Unlock()
|
|
||||||
|
|
||||||
debug("stop all services")
|
|
||||||
|
|
||||||
stopAllServices(services)
|
|
||||||
exitCode = s.cmd.ProcessState.ExitCode()
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
|
|
||||||
debug("run service [%s]", s.CMD)
|
debug("run service [%s]", s.CMD)
|
||||||
err := s.cmd.Run()
|
err := s.cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErr(err)
|
printErr(err)
|
||||||
}
|
}
|
||||||
debug("service [%s] done, err: [%v]", s.CMD, err)
|
|
||||||
}(w)
|
go func(s *Service, w *io.PipeWriter) {
|
||||||
|
s.cmd.Wait()
|
||||||
|
w.Close()
|
||||||
|
debug("service done [%s]", s.CMD)
|
||||||
|
}(s, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.Unlock()
|
return nil
|
||||||
|
|
||||||
debug("wait servises")
|
|
||||||
wg.Wait()
|
|
||||||
debug("all servises stoped")
|
|
||||||
|
|
||||||
return exitCode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfig(cfg *Config, configFile string) error {
|
func loadConfig(cfg *Config, configFile string) error {
|
||||||
@ -172,18 +161,24 @@ func forwardSignals2(services []*Service) {
|
|||||||
sigCh := make(chan os.Signal, 1)
|
sigCh := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigCh, syscall.SIGCHLD)
|
signal.Notify(sigCh, syscall.SIGCHLD)
|
||||||
|
|
||||||
for _ = range sigCh {
|
var once sync.Once
|
||||||
printInfo("chld")
|
|
||||||
for _, c := range services {
|
|
||||||
if c.cmd.ProcessState != nil {
|
|
||||||
|
|
||||||
|
for range sigCh {
|
||||||
|
debug("chld")
|
||||||
|
for _, c := range services {
|
||||||
|
debug("%v", c.cmd.ProcessState)
|
||||||
|
if c.cmd.ProcessState != nil {
|
||||||
|
once.Do(func() {
|
||||||
|
debug("stop all services")
|
||||||
|
stopAllServices(services)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
verbose = true
|
verbose = false
|
||||||
|
|
||||||
err := unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)
|
err := unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -192,6 +187,7 @@ func main() {
|
|||||||
|
|
||||||
var configFile string
|
var configFile string
|
||||||
flag.StringVar(&configFile, "c", "./config.json", "JSON config file")
|
flag.StringVar(&configFile, "c", "./config.json", "JSON config file")
|
||||||
|
flag.BoolVar(&verbose, "v", false, "Show debug output")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
var cfg Config
|
var cfg Config
|
||||||
@ -205,6 +201,8 @@ func main() {
|
|||||||
go forwardSignals(cfg.Services)
|
go forwardSignals(cfg.Services)
|
||||||
go forwardSignals2(cfg.Services)
|
go forwardSignals2(cfg.Services)
|
||||||
|
|
||||||
exitCode := runServices(cfg.Services)
|
runServices(cfg.Services)
|
||||||
os.Exit(exitCode)
|
//os.Exit(exitCode)
|
||||||
|
|
||||||
|
<-ch
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user