package main import ( "context" "flag" "fmt" "os" "os/signal" "syscall" "time" lfcc "git.loafle.net/commons_go/config" "git.loafle.net/commons_go/logging" "git.loafle.net/overflow/overflow_probes/auth" "git.loafle.net/overflow/overflow_probes/commons" "git.loafle.net/overflow/overflow_probes/config" "git.loafle.net/overflow/overflow_probes/probe" "github.com/takama/daemon" ) const ( version = "1.0.0" website = "https://www.overflow.cloud" banner = ` ██████╗ ██╗ ██╗███████╗██████╗ ███████╗██╗ ██████╗ ██╗ ██╗ ██╔═══██╗██║ ██║██╔════╝██╔══██╗██╔════╝██║ ██╔═══██╗██║ ██║ ██║ ██║██║ ██║█████╗ ██████╔╝█████╗ ██║ ██║ ██║██║ █╗ ██║ ██║ ██║╚██╗ ██╔╝██╔══╝ ██╔══██╗██╔══╝ ██║ ██║ ██║██║███╗██║ ╚██████╔╝ ╚████╔╝ ███████╗██║ ██║██║ ███████╗╚██████╔╝╚███╔███╔╝ ╚═════╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝ ╚═════╝ ╚══╝╚══╝ ` ) const ( // name of the service serviceName = "Probe" serviceDescription = "Probe Service of overFlow" ) type daemonHandler struct { daemon.Daemon } // Manage by daemon commands or run the daemon // cmd install -config=./path // cmd install // cmd remove // cmd start // cmd stop // cmd status // cmd -config=./path // cmd func (d *daemonHandler) Manage() (isRunning bool, status string, err error) { isRunning = true if nil != daemonCommand { switch *daemonCommand { case "install": var runArgs = []string{} runArgs = append(runArgs, fmt.Sprintf("-configDir=%s", *configDir)) isRunning = false status, err = d.Install(runArgs...) case "remove": isRunning = false status, err = d.Remove() case "start": isRunning = false status, err = d.Start() case "stop": isRunning = false status, err = d.Stop() case "status": isRunning = false status, err = d.Status() } } return } var ( daemonCommand *string configDir *string ) func init() { flag.Usage = func() { fmt.Printf("Usage of %s\n", os.Args[0]) fmt.Printf(" [install | remove | start | stop | status]\n") flag.PrintDefaults() } if len(os.Args) > 1 { command := os.Args[1] switch command { case "install", "remove", "start", "stop", "status": *daemonCommand = command } } configDir = flag.String("config-dir", ".", "The directory of config") flag.Parse() } func main() { var err error var srv daemon.Daemon var status string var handler commons.Handler isRunning := true var confDir string defer logging.Logger.Sync() fmt.Println(banner) fmt.Printf("Version: %s\n", version) fmt.Printf("URL: %s\n", website) fmt.Println() if dir, err := lfcc.ABSPathify(*configDir); nil != err { logging.Logger.Panic(fmt.Sprintf("Probe: config path[%s] is not valid", *configDir)) } else { logging.Logger.Debug(fmt.Sprintf("Probe: config path[%s]", dir)) confDir = dir } conf := lfcc.New() conf.SetConfigPath(*configDir) if err := conf.Load(&config.Config, "config.json"); nil != err { logging.Logger.Panic(fmt.Sprintf("Probe: config is not valid error[%v]", err)) } if srv, err = daemon.New(serviceName, serviceDescription); nil != err { logging.Logger.Panic(fmt.Sprintf("Probe: %v", err)) } s := &daemonHandler{srv} if isRunning, status, err = s.Manage(); nil != err { logging.Logger.Error(fmt.Sprintf("Probe: status[%s] error: %v", status, err)) os.Exit(1) } if !isRunning { logging.Logger.Info(fmt.Sprintf("Probe: status[%s]", status)) os.Exit(0) } if handler, err = auth.New(confDir); nil != err { logging.Logger.Error(fmt.Sprintf("Auth: error: %v", err)) os.Exit(1) } go func() { if err := handler.Serve(); err != nil { logging.Logger.Error(fmt.Sprintf("Probe: Authenticator error: %v", err)) return } handler = probe.New(confDir) if err := handler.Serve(); err != nil { logging.Logger.Error(fmt.Sprintf("Probe: error: %v", err)) return } }() // // Set up channel on which to send signal notifications. // // We must use a buffered channel or risk missing the signal // // if we're not ready to receive when the signal is sent. interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, syscall.SIGKILL, syscall.SIGSTOP, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) <-interrupt ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := handler.Shutdown(ctx); err != nil { logging.Logger.Error(fmt.Sprintf("Probe: status[%s] error: %v", status, err)) } // // loop work cycle with accept connections or interrupt // // by system signal // ListenLoop: // for { // select { // case s := <-interrupt: // logging.Logger.Info(fmt.Sprintf("Probe: signal[%v]", s)) // ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) // defer cancel() // if err := p.Shutdown(ctx); err != nil { // logging.Logger.Error(fmt.Sprintf("Probe: status[%s] error: %v", status, err)) // } // if s == os.Interrupt { // logging.Logger.Info("Probe was interruped by system signal") // } else { // logging.Logger.Info("Probe was killed") // } // break ListenLoop // } // } }