mirror of
https://github.com/XrayR-project/XrayR.git
synced 2025-06-07 21:09:53 +00:00

The standard "log" package was replaced by the structured logger "github.com/sirupsen/logrus" for better log control in various files. This change will allow to tailor the logging information more precisely and make logs easier to read and analyze. All calls of standard log methods were replaced by their logrus counterparts.
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"path"
|
|
"runtime"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
|
|
"github.com/XrayR-project/XrayR/panel"
|
|
)
|
|
|
|
var (
|
|
cfgFile string
|
|
rootCmd = &cobra.Command{
|
|
Use: "XrayR",
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
if err := run(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
},
|
|
}
|
|
)
|
|
|
|
func init() {
|
|
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file for XrayR.")
|
|
}
|
|
|
|
func getConfig() *viper.Viper {
|
|
config := viper.New()
|
|
|
|
// Set custom path and name
|
|
if cfgFile != "" {
|
|
configName := path.Base(cfgFile)
|
|
configFileExt := path.Ext(cfgFile)
|
|
configNameOnly := strings.TrimSuffix(configName, configFileExt)
|
|
configPath := path.Dir(cfgFile)
|
|
config.SetConfigName(configNameOnly)
|
|
config.SetConfigType(strings.TrimPrefix(configFileExt, "."))
|
|
config.AddConfigPath(configPath)
|
|
// Set ASSET Path and Config Path for XrayR
|
|
os.Setenv("XRAY_LOCATION_ASSET", configPath)
|
|
os.Setenv("XRAY_LOCATION_CONFIG", configPath)
|
|
} else {
|
|
// Set default config path
|
|
config.SetConfigName("config")
|
|
config.SetConfigType("yml")
|
|
config.AddConfigPath(".")
|
|
|
|
}
|
|
|
|
if err := config.ReadInConfig(); err != nil {
|
|
log.Panicf("Config file error: %s \n", err)
|
|
}
|
|
|
|
config.WatchConfig() // Watch the config
|
|
|
|
return config
|
|
}
|
|
|
|
func run() error {
|
|
showVersion()
|
|
|
|
config := getConfig()
|
|
panelConfig := &panel.Config{}
|
|
if err := config.Unmarshal(panelConfig); err != nil {
|
|
return fmt.Errorf("Parse config file %v failed: %s \n", cfgFile, err)
|
|
}
|
|
p := panel.New(panelConfig)
|
|
lastTime := time.Now()
|
|
config.OnConfigChange(func(e fsnotify.Event) {
|
|
// Discarding event received within a short period of time after receiving an event.
|
|
if time.Now().After(lastTime.Add(3 * time.Second)) {
|
|
// Hot reload function
|
|
fmt.Println("Config file changed:", e.Name)
|
|
p.Close()
|
|
// Delete old instance and trigger GC
|
|
runtime.GC()
|
|
if err := config.Unmarshal(panelConfig); err != nil {
|
|
log.Panicf("Parse config file %v failed: %s \n", cfgFile, err)
|
|
}
|
|
p.Start()
|
|
lastTime = time.Now()
|
|
}
|
|
})
|
|
p.Start()
|
|
defer p.Close()
|
|
|
|
// Explicitly triggering GC to remove garbage from config loading.
|
|
runtime.GC()
|
|
// Running backend
|
|
osSignals := make(chan os.Signal, 1)
|
|
signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM)
|
|
<-osSignals
|
|
|
|
return nil
|
|
}
|
|
|
|
func Execute() error {
|
|
return rootCmd.Execute()
|
|
}
|