From 4847f9ee9f30a48a64bd452c581d7d5703b2f1b9 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Fri, 31 Mar 2023 14:51:08 +0800 Subject: [PATCH] add support for windows service --- cmd/gost/config.go | 4 +- cmd/gost/main.go | 198 ++------------------------------------------ cmd/gost/program.go | 197 +++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + 5 files changed, 208 insertions(+), 194 deletions(-) create mode 100644 cmd/gost/program.go diff --git a/cmd/gost/config.go b/cmd/gost/config.go index 75e684d..2bc9250 100644 --- a/cmd/gost/config.go +++ b/cmd/gost/config.go @@ -21,6 +21,8 @@ func buildService(cfg *config.Config) (services []service.Service) { return } + log := logger.Default() + for _, autherCfg := range cfg.Authers { if auther := parsing.ParseAuther(autherCfg); auther != nil { if err := registry.AutherRegistry().Register(autherCfg.Name, auther); err != nil { @@ -172,7 +174,7 @@ func logFromConfig(cfg *config.LogConfig) logger.Logger { os.MkdirAll(filepath.Dir(cfg.Output), 0755) f, err := os.OpenFile(cfg.Output, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { - log.Warn(err) + logger.Default().Warn(err) } else { out = f } diff --git a/cmd/gost/main.go b/cmd/gost/main.go index ae79562..0f6c3ef 100644 --- a/cmd/gost/main.go +++ b/cmd/gost/main.go @@ -4,27 +4,20 @@ import ( "context" "flag" "fmt" - "net/http" + "log" _ "net/http/pprof" "os" "os/exec" - "os/signal" "runtime" "strings" "sync" - "syscall" "github.com/go-gost/core/logger" - "github.com/go-gost/x/config" - "github.com/go-gost/x/config/parsing" xlogger "github.com/go-gost/x/logger" - xmetrics "github.com/go-gost/x/metrics" - "github.com/go-gost/x/registry" + "github.com/judwhite/go-svc" ) var ( - log logger.Logger - cfgFile string outputFormat string services stringList @@ -93,193 +86,12 @@ func init() { os.Exit(0) } - log = xlogger.NewLogger() - logger.SetDefault(log) + logger.SetDefault(xlogger.NewLogger()) } func main() { - cfg := &config.Config{} - if cfgFile != "" { - if err := cfg.ReadFile(cfgFile); err != nil { - log.Fatal(err) - } - } - - cmdCfg, err := buildConfigFromCmd(services, nodes) - if err != nil { + p := &program{} + if err := svc.Run(p); err != nil { log.Fatal(err) } - cfg = mergeConfig(cfg, cmdCfg) - - if len(cfg.Services) == 0 && apiAddr == "" { - if err := cfg.Load(); err != nil { - log.Fatal(err) - } - } - - if v := os.Getenv("GOST_PROFILING"); v != "" { - cfg.Profiling = &config.ProfilingConfig{ - Addr: v, - } - } - if v := os.Getenv("GOST_METRICS"); v != "" { - cfg.Metrics = &config.MetricsConfig{ - Addr: v, - } - } - - if v := os.Getenv("GOST_LOGGER_LEVEL"); v != "" { - cfg.Log = &config.LogConfig{ - Level: v, - } - } - - if v := os.Getenv("GOST_API"); v != "" { - cfg.API = &config.APIConfig{ - Addr: v, - } - } - - if debug { - if cfg.Log == nil { - cfg.Log = &config.LogConfig{} - } - cfg.Log.Level = string(logger.DebugLevel) - } - if apiAddr != "" { - cfg.API = &config.APIConfig{ - Addr: apiAddr, - } - } - if metricsAddr != "" { - cfg.Metrics = &config.MetricsConfig{ - Addr: metricsAddr, - } - } - - log = logFromConfig(cfg.Log) - - logger.SetDefault(log) - - if outputFormat != "" { - if err := cfg.Write(os.Stdout, outputFormat); err != nil { - log.Fatal(err) - } - os.Exit(0) - } - - if cfg.Profiling != nil { - go func() { - addr := cfg.Profiling.Addr - if addr == "" { - addr = ":6060" - } - log.Info("profiling server on ", addr) - log.Fatal(http.ListenAndServe(addr, nil)) - }() - } - - if cfg.API != nil { - s, err := buildAPIService(cfg.API) - if err != nil { - log.Fatal(err) - } - defer s.Close() - - go func() { - log.Info("api service on ", s.Addr()) - log.Fatal(s.Serve()) - }() - } - - if cfg.Metrics != nil { - xmetrics.Init(xmetrics.NewMetrics()) - if cfg.Metrics.Addr != "" { - s, err := buildMetricsService(cfg.Metrics) - if err != nil { - log.Fatal(err) - } - go func() { - defer s.Close() - log.Info("metrics service on ", s.Addr()) - log.Fatal(s.Serve()) - }() - } - } - - parsing.BuildDefaultTLSConfig(cfg.TLS) - - services := buildService(cfg) - for _, svc := range services { - svc := svc - go func() { - svc.Serve() - // svc.Close() - }() - } - - config.Set(cfg) - - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP) - - for sig := range sigs { - switch sig { - case syscall.SIGHUP: - return - default: - for name, srv := range registry.ServiceRegistry().GetAll() { - srv.Close() - log.Debugf("service %s shutdown", name) - } - return - } - } -} - -func mergeConfig(cfg1, cfg2 *config.Config) *config.Config { - if cfg1 == nil { - return cfg2 - } - if cfg2 == nil { - return cfg1 - } - - cfg := &config.Config{ - Services: append(cfg1.Services, cfg2.Services...), - Chains: append(cfg1.Chains, cfg2.Chains...), - Hops: append(cfg1.Hops, cfg2.Hops...), - Authers: append(cfg1.Authers, cfg2.Authers...), - Admissions: append(cfg1.Admissions, cfg2.Admissions...), - Bypasses: append(cfg1.Bypasses, cfg2.Bypasses...), - Resolvers: append(cfg1.Resolvers, cfg2.Resolvers...), - Hosts: append(cfg1.Hosts, cfg2.Hosts...), - Ingresses: append(cfg1.Ingresses, cfg2.Ingresses...), - Recorders: append(cfg1.Recorders, cfg2.Recorders...), - Limiters: append(cfg1.Limiters, cfg2.Limiters...), - CLimiters: append(cfg1.CLimiters, cfg2.CLimiters...), - RLimiters: append(cfg1.RLimiters, cfg2.RLimiters...), - TLS: cfg1.TLS, - Log: cfg1.Log, - API: cfg1.API, - Metrics: cfg1.Metrics, - Profiling: cfg1.Profiling, - } - if cfg2.TLS != nil { - cfg.TLS = cfg2.TLS - } - if cfg2.Log != nil { - cfg.Log = cfg2.Log - } - if cfg2.API != nil { - cfg.API = cfg2.API - } - if cfg2.Metrics != nil { - cfg.Metrics = cfg2.Metrics - } - if cfg2.Profiling != nil { - cfg.Profiling = cfg2.Profiling - } - - return cfg } diff --git a/cmd/gost/program.go b/cmd/gost/program.go new file mode 100644 index 0000000..2cf5516 --- /dev/null +++ b/cmd/gost/program.go @@ -0,0 +1,197 @@ +package main + +import ( + "net/http" + "os" + + "github.com/go-gost/core/logger" + "github.com/go-gost/x/config" + "github.com/go-gost/x/config/parsing" + xmetrics "github.com/go-gost/x/metrics" + "github.com/go-gost/x/registry" + "github.com/judwhite/go-svc" +) + +type program struct { +} + +func (p *program) Init(env svc.Environment) error { + cfg := &config.Config{} + if cfgFile != "" { + if err := cfg.ReadFile(cfgFile); err != nil { + return err + } + } + + cmdCfg, err := buildConfigFromCmd(services, nodes) + if err != nil { + return err + } + cfg = p.mergeConfig(cfg, cmdCfg) + + if len(cfg.Services) == 0 && apiAddr == "" { + if err := cfg.Load(); err != nil { + return err + } + } + + if v := os.Getenv("GOST_API"); v != "" { + cfg.API = &config.APIConfig{ + Addr: v, + } + } + if v := os.Getenv("GOST_LOGGER_LEVEL"); v != "" { + cfg.Log = &config.LogConfig{ + Level: v, + } + } + if v := os.Getenv("GOST_PROFILING"); v != "" { + cfg.Profiling = &config.ProfilingConfig{ + Addr: v, + } + } + if v := os.Getenv("GOST_METRICS"); v != "" { + cfg.Metrics = &config.MetricsConfig{ + Addr: v, + } + } + + if apiAddr != "" { + cfg.API = &config.APIConfig{ + Addr: apiAddr, + } + } + if debug { + if cfg.Log == nil { + cfg.Log = &config.LogConfig{} + } + cfg.Log.Level = string(logger.DebugLevel) + } + if metricsAddr != "" { + cfg.Metrics = &config.MetricsConfig{ + Addr: metricsAddr, + } + } + + logger.SetDefault(logFromConfig(cfg.Log)) + + if outputFormat != "" { + if err := cfg.Write(os.Stdout, outputFormat); err != nil { + return err + } + os.Exit(0) + } + + parsing.BuildDefaultTLSConfig(cfg.TLS) + + config.Set(cfg) + + return nil +} + +func (p *program) Start() error { + log := logger.Default() + cfg := config.Global() + + if cfg.API != nil { + s, err := buildAPIService(cfg.API) + if err != nil { + return err + } + defer s.Close() + + go func() { + log.Info("api service on ", s.Addr()) + log.Fatal(s.Serve()) + }() + } + if cfg.Profiling != nil { + go func() { + addr := cfg.Profiling.Addr + if addr == "" { + addr = ":6060" + } + log.Info("profiling server on ", addr) + log.Fatal(http.ListenAndServe(addr, nil)) + }() + } + + if cfg.Metrics != nil { + xmetrics.Init(xmetrics.NewMetrics()) + if cfg.Metrics.Addr != "" { + s, err := buildMetricsService(cfg.Metrics) + if err != nil { + log.Fatal(err) + } + go func() { + defer s.Close() + log.Info("metrics service on ", s.Addr()) + log.Fatal(s.Serve()) + }() + } + } + + for _, svc := range buildService(cfg) { + svc := svc + go func() { + svc.Serve() + }() + } + + return nil +} + +func (p *program) Stop() error { + for name, srv := range registry.ServiceRegistry().GetAll() { + srv.Close() + logger.Default().Debugf("service %s shutdown", name) + } + return nil +} + +func (p *program) mergeConfig(cfg1, cfg2 *config.Config) *config.Config { + if cfg1 == nil { + return cfg2 + } + if cfg2 == nil { + return cfg1 + } + + cfg := &config.Config{ + Services: append(cfg1.Services, cfg2.Services...), + Chains: append(cfg1.Chains, cfg2.Chains...), + Hops: append(cfg1.Hops, cfg2.Hops...), + Authers: append(cfg1.Authers, cfg2.Authers...), + Admissions: append(cfg1.Admissions, cfg2.Admissions...), + Bypasses: append(cfg1.Bypasses, cfg2.Bypasses...), + Resolvers: append(cfg1.Resolvers, cfg2.Resolvers...), + Hosts: append(cfg1.Hosts, cfg2.Hosts...), + Ingresses: append(cfg1.Ingresses, cfg2.Ingresses...), + Recorders: append(cfg1.Recorders, cfg2.Recorders...), + Limiters: append(cfg1.Limiters, cfg2.Limiters...), + CLimiters: append(cfg1.CLimiters, cfg2.CLimiters...), + RLimiters: append(cfg1.RLimiters, cfg2.RLimiters...), + TLS: cfg1.TLS, + Log: cfg1.Log, + API: cfg1.API, + Metrics: cfg1.Metrics, + Profiling: cfg1.Profiling, + } + if cfg2.TLS != nil { + cfg.TLS = cfg2.TLS + } + if cfg2.Log != nil { + cfg.Log = cfg2.Log + } + if cfg2.API != nil { + cfg.API = cfg2.API + } + if cfg2.Metrics != nil { + cfg.Metrics = cfg2.Metrics + } + if cfg2.Profiling != nil { + cfg.Profiling = cfg2.Profiling + } + + return cfg +} diff --git a/go.mod b/go.mod index 5f2c5aa..377907a 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ replace github.com/templexxx/cpu v0.0.7 => github.com/templexxx/cpu v0.0.10-0.20 require ( github.com/go-gost/core v0.0.0-20230131100536-f3482d7cd848 github.com/go-gost/x v0.0.0-20230321102805-18fa84b51f1d + github.com/judwhite/go-svc v1.2.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) diff --git a/go.sum b/go.sum index ab1b92b..98fe453 100644 --- a/go.sum +++ b/go.sum @@ -220,6 +220,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/judwhite/go-svc v1.2.1 h1:a7fsJzYUa33sfDJRF2N/WXhA+LonCEEY8BJb1tuS5tA= +github.com/judwhite/go-svc v1.2.1/go.mod h1:mo/P2JNX8C07ywpP9YtO2gnBgnUiFTHqtsZekJrUuTk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=