github.com/metacubex/mihomo@v1.18.5/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"os/signal"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strings"
    11  	"syscall"
    12  
    13  	"github.com/metacubex/mihomo/component/updater"
    14  	"github.com/metacubex/mihomo/config"
    15  	C "github.com/metacubex/mihomo/constant"
    16  	"github.com/metacubex/mihomo/constant/features"
    17  	"github.com/metacubex/mihomo/hub"
    18  	"github.com/metacubex/mihomo/hub/executor"
    19  	"github.com/metacubex/mihomo/log"
    20  
    21  	"go.uber.org/automaxprocs/maxprocs"
    22  )
    23  
    24  var (
    25  	version                bool
    26  	testConfig             bool
    27  	geodataMode            bool
    28  	homeDir                string
    29  	configFile             string
    30  	externalUI             string
    31  	externalController     string
    32  	externalControllerUnix string
    33  	secret                 string
    34  )
    35  
    36  func init() {
    37  	flag.StringVar(&homeDir, "d", os.Getenv("CLASH_HOME_DIR"), "set configuration directory")
    38  	flag.StringVar(&configFile, "f", os.Getenv("CLASH_CONFIG_FILE"), "specify configuration file")
    39  	flag.StringVar(&externalUI, "ext-ui", os.Getenv("CLASH_OVERRIDE_EXTERNAL_UI_DIR"), "override external ui directory")
    40  	flag.StringVar(&externalController, "ext-ctl", os.Getenv("CLASH_OVERRIDE_EXTERNAL_CONTROLLER"), "override external controller address")
    41  	flag.StringVar(&externalControllerUnix, "ext-ctl-unix", os.Getenv("CLASH_OVERRIDE_EXTERNAL_CONTROLLER_UNIX"), "override external controller unix address")
    42  	flag.StringVar(&secret, "secret", os.Getenv("CLASH_OVERRIDE_SECRET"), "override secret for RESTful API")
    43  	flag.BoolVar(&geodataMode, "m", false, "set geodata mode")
    44  	flag.BoolVar(&version, "v", false, "show current version of mihomo")
    45  	flag.BoolVar(&testConfig, "t", false, "test configuration and exit")
    46  	flag.Parse()
    47  }
    48  
    49  func main() {
    50  	_, _ = maxprocs.Set(maxprocs.Logger(func(string, ...any) {}))
    51  	if version {
    52  		fmt.Printf("Mihomo Meta %s %s %s with %s %s\n",
    53  			C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime)
    54  		if tags := features.Tags(); len(tags) != 0 {
    55  			fmt.Printf("Use tags: %s\n", strings.Join(tags, ", "))
    56  		}
    57  
    58  		return
    59  	}
    60  
    61  	if homeDir != "" {
    62  		if !filepath.IsAbs(homeDir) {
    63  			currentDir, _ := os.Getwd()
    64  			homeDir = filepath.Join(currentDir, homeDir)
    65  		}
    66  		C.SetHomeDir(homeDir)
    67  	}
    68  
    69  	if configFile != "" {
    70  		if !filepath.IsAbs(configFile) {
    71  			currentDir, _ := os.Getwd()
    72  			configFile = filepath.Join(currentDir, configFile)
    73  		}
    74  	} else {
    75  		configFile = filepath.Join(C.Path.HomeDir(), C.Path.Config())
    76  	}
    77  	C.SetConfig(configFile)
    78  
    79  	if geodataMode {
    80  		C.GeodataMode = true
    81  	}
    82  
    83  	if err := config.Init(C.Path.HomeDir()); err != nil {
    84  		log.Fatalln("Initial configuration directory error: %s", err.Error())
    85  	}
    86  
    87  	if testConfig {
    88  		if _, err := executor.Parse(); err != nil {
    89  			log.Errorln(err.Error())
    90  			fmt.Printf("configuration file %s test failed\n", C.Path.Config())
    91  			os.Exit(1)
    92  		}
    93  		fmt.Printf("configuration file %s test is successful\n", C.Path.Config())
    94  		return
    95  	}
    96  
    97  	var options []hub.Option
    98  	if externalUI != "" {
    99  		options = append(options, hub.WithExternalUI(externalUI))
   100  	}
   101  	if externalController != "" {
   102  		options = append(options, hub.WithExternalController(externalController))
   103  	}
   104  	if externalControllerUnix != "" {
   105  		options = append(options, hub.WithExternalControllerUnix(externalControllerUnix))
   106  	}
   107  	if secret != "" {
   108  		options = append(options, hub.WithSecret(secret))
   109  	}
   110  
   111  	if err := hub.Parse(options...); err != nil {
   112  		log.Fatalln("Parse config error: %s", err.Error())
   113  	}
   114  
   115  	if C.GeoAutoUpdate {
   116  		updater.RegisterGeoUpdater()
   117  	}
   118  
   119  	defer executor.Shutdown()
   120  
   121  	termSign := make(chan os.Signal, 1)
   122  	hupSign := make(chan os.Signal, 1)
   123  	signal.Notify(termSign, syscall.SIGINT, syscall.SIGTERM)
   124  	signal.Notify(hupSign, syscall.SIGHUP)
   125  	for {
   126  		select {
   127  		case <-termSign:
   128  			return
   129  		case <-hupSign:
   130  			if cfg, err := executor.ParseWithPath(C.Path.Config()); err == nil {
   131  				executor.ApplyConfig(cfg, true)
   132  			} else {
   133  				log.Errorln("Parse config error: %s", err.Error())
   134  			}
   135  		}
   136  	}
   137  }