github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/cmd/shadowsocks-go/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "flag" 6 "fmt" 7 "os" 8 "os/signal" 9 "syscall" 10 11 "github.com/database64128/shadowsocks-go/jsonhelper" 12 "github.com/database64128/shadowsocks-go/logging" 13 "github.com/database64128/shadowsocks-go/service" 14 "go.uber.org/zap" 15 "go.uber.org/zap/zapcore" 16 ) 17 18 var ( 19 testConf bool 20 confPath string 21 zapConf string 22 logLevel zapcore.Level 23 ) 24 25 func init() { 26 flag.BoolVar(&testConf, "testConf", false, "Test the configuration file without starting the services") 27 flag.StringVar(&confPath, "confPath", "", "Path to JSON configuration file") 28 flag.StringVar(&zapConf, "zapConf", "", "Preset name or path to JSON configuration file for building the zap logger.\nAvailable presets: console (default), systemd, production, development") 29 flag.TextVar(&logLevel, "logLevel", zapcore.InvalidLevel, "Override the logger configuration's log level.\nAvailable levels: debug, info, warn, error, dpanic, panic, fatal") 30 } 31 32 func main() { 33 flag.Parse() 34 35 if confPath == "" { 36 fmt.Println("Missing -confPath <path>.") 37 flag.Usage() 38 os.Exit(1) 39 } 40 41 var ( 42 zc zap.Config 43 sc service.Config 44 ) 45 46 switch zapConf { 47 case "console", "": 48 zc = logging.NewProductionConsoleConfig(false) 49 case "systemd": 50 zc = logging.NewProductionConsoleConfig(true) 51 case "production": 52 zc = zap.NewProductionConfig() 53 case "development": 54 zc = zap.NewDevelopmentConfig() 55 default: 56 if err := jsonhelper.LoadAndDecodeDisallowUnknownFields(zapConf, &zc); err != nil { 57 fmt.Println(err) 58 os.Exit(1) 59 } 60 } 61 62 if logLevel != zapcore.InvalidLevel { 63 zc.Level.SetLevel(logLevel) 64 } 65 66 logger, err := zc.Build() 67 if err != nil { 68 fmt.Println(err) 69 os.Exit(1) 70 } 71 defer logger.Sync() 72 73 if err = jsonhelper.LoadAndDecodeDisallowUnknownFields(confPath, &sc); err != nil { 74 logger.Fatal("Failed to load config", 75 zap.String("confPath", confPath), 76 zap.Error(err), 77 ) 78 } 79 80 m, err := sc.Manager(logger) 81 if err != nil { 82 logger.Fatal("Failed to create service manager", 83 zap.String("confPath", confPath), 84 zap.Error(err), 85 ) 86 } 87 defer m.Close() 88 89 if testConf { 90 logger.Info("Config test OK", zap.String("confPath", confPath)) 91 return 92 } 93 94 ctx, cancel := context.WithCancel(context.Background()) 95 96 go func() { 97 sigCh := make(chan os.Signal, 1) 98 signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) 99 sig := <-sigCh 100 logger.Info("Received exit signal", zap.Stringer("signal", sig)) 101 cancel() 102 }() 103 104 if err = m.Start(ctx); err != nil { 105 logger.Fatal("Failed to start services", 106 zap.String("confPath", confPath), 107 zap.Error(err), 108 ) 109 } 110 111 <-ctx.Done() 112 m.Stop() 113 }