123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- package main
- import (
- "flag"
- "fmt"
- "os"
- "os/signal"
- "path/filepath"
- "runtime"
- "strings"
- "syscall"
- "github.com/metacubex/mihomo/component/updater"
- "github.com/metacubex/mihomo/config"
- C "github.com/metacubex/mihomo/constant"
- "github.com/metacubex/mihomo/constant/features"
- "github.com/metacubex/mihomo/hub"
- "github.com/metacubex/mihomo/hub/executor"
- "github.com/metacubex/mihomo/log"
- "github.com/metacubex/mihomo/rules/provider"
- "go.uber.org/automaxprocs/maxprocs"
- )
- var (
- version bool
- testConfig bool
- geodataMode bool
- homeDir string
- configFile string
- externalUI string
- externalController string
- externalControllerUnix string
- secret string
- )
- func init() {
- flag.StringVar(&homeDir, "d", os.Getenv("CLASH_HOME_DIR"), "set configuration directory")
- flag.StringVar(&configFile, "f", os.Getenv("CLASH_CONFIG_FILE"), "specify configuration file")
- flag.StringVar(&externalUI, "ext-ui", os.Getenv("CLASH_OVERRIDE_EXTERNAL_UI_DIR"), "override external ui directory")
- flag.StringVar(&externalController, "ext-ctl", os.Getenv("CLASH_OVERRIDE_EXTERNAL_CONTROLLER"), "override external controller address")
- flag.StringVar(&externalControllerUnix, "ext-ctl-unix", os.Getenv("CLASH_OVERRIDE_EXTERNAL_CONTROLLER_UNIX"), "override external controller unix address")
- flag.StringVar(&secret, "secret", os.Getenv("CLASH_OVERRIDE_SECRET"), "override secret for RESTful API")
- flag.BoolVar(&geodataMode, "m", false, "set geodata mode")
- flag.BoolVar(&version, "v", false, "show current version of mihomo")
- flag.BoolVar(&testConfig, "t", false, "test configuration and exit")
- flag.Parse()
- }
- func main() {
- _, _ = maxprocs.Set(maxprocs.Logger(func(string, ...any) {}))
- if len(os.Args) > 1 && os.Args[1] == "convert-ruleset" {
- provider.ConvertMain(os.Args[2:])
- return
- }
- if version {
- fmt.Printf("Mihomo Meta %s %s %s with %s %s\n",
- C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime)
- if tags := features.Tags(); len(tags) != 0 {
- fmt.Printf("Use tags: %s\n", strings.Join(tags, ", "))
- }
- return
- }
- if homeDir != "" {
- if !filepath.IsAbs(homeDir) {
- currentDir, _ := os.Getwd()
- homeDir = filepath.Join(currentDir, homeDir)
- }
- C.SetHomeDir(homeDir)
- }
- if configFile != "" {
- if !filepath.IsAbs(configFile) {
- currentDir, _ := os.Getwd()
- configFile = filepath.Join(currentDir, configFile)
- }
- } else {
- configFile = filepath.Join(C.Path.HomeDir(), C.Path.Config())
- }
- C.SetConfig(configFile)
- if geodataMode {
- C.GeodataMode = true
- }
- if err := config.Init(C.Path.HomeDir()); err != nil {
- log.Fatalln("Initial configuration directory error: %s", err.Error())
- }
- if testConfig {
- if _, err := executor.Parse(); err != nil {
- log.Errorln(err.Error())
- fmt.Printf("configuration file %s test failed\n", C.Path.Config())
- os.Exit(1)
- }
- fmt.Printf("configuration file %s test is successful\n", C.Path.Config())
- return
- }
- var options []hub.Option
- if externalUI != "" {
- options = append(options, hub.WithExternalUI(externalUI))
- }
- if externalController != "" {
- options = append(options, hub.WithExternalController(externalController))
- }
- if externalControllerUnix != "" {
- options = append(options, hub.WithExternalControllerUnix(externalControllerUnix))
- }
- if secret != "" {
- options = append(options, hub.WithSecret(secret))
- }
- if err := hub.Parse(options...); err != nil {
- log.Fatalln("Parse config error: %s", err.Error())
- }
- if C.GeoAutoUpdate {
- updater.RegisterGeoUpdater(func() {
- cfg, err := executor.ParseWithPath(C.Path.Config())
- if err != nil {
- log.Errorln("[GEO] update GEO databases failed: %v", err)
- return
- }
- log.Warnln("[GEO] update GEO databases success, applying config")
- executor.ApplyConfig(cfg, false)
- })
- }
- defer executor.Shutdown()
- termSign := make(chan os.Signal, 1)
- hupSign := make(chan os.Signal, 1)
- signal.Notify(termSign, syscall.SIGINT, syscall.SIGTERM)
- signal.Notify(hupSign, syscall.SIGHUP)
- for {
- select {
- case <-termSign:
- return
- case <-hupSign:
- if cfg, err := executor.ParseWithPath(C.Path.Config()); err == nil {
- executor.ApplyConfig(cfg, true)
- } else {
- log.Errorln("Parse config error: %s", err.Error())
- }
- }
- }
- }
|