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  }