nezhahq / nezha

:trollface: Self-hosted, lightweight server and website monitoring and O&M tool
https://nezha.wiki
Apache License 2.0
7.32k stars 1.28k forks source link

fix(cli): display version without initializing app #463

Closed Moraxyc closed 3 weeks ago

Moraxyc commented 3 weeks ago

This PR separates "showing version" from the entire program.

According to the original code, running "./dashboard -v" will produce the following errors:

panic: open data/config.yaml: no such file or directory

goroutine 1 [running]:
github.com/naiba/nezha/service/singleton.InitConfigFromPath(...)
github.com/naiba/nezha/service/singleton/singleton.go:49
main.init.0()
github.com/naiba/nezha/cmd/dashboard/main.go:37 +0x20b

In Go, the init() will run before the main(), and some codes in init() initialize the service. Therefore, we can check the version flag in the init stage, and after the version is displayed, the program exits.

uubulb commented 3 weeks ago

I think the the program should exit after printing version number. That's the common case

Moraxyc commented 3 weeks ago

please take a look again @uubulb

uubulb commented 3 weeks ago

please take a look again @uubulb

wait for the maintainer to review

naiba commented 3 weeks ago

可以把 init 里面的东西放到 main 中延后初始化而不是把 main 中的东西放到 init 哈 init 都懒用了

Moraxyc commented 3 weeks ago

直接不使用init嘛? @naiba

大概这样?

func main() {
    flag.CommandLine.ParseErrorsWhitelist.UnknownFlags = true
    flag.BoolVarP(&dashboardCliParam.Version, "version", "v", false, "查看当前版本号")
    flag.StringVarP(&dashboardCliParam.ConfigFile, "config", "c", "data/config.yaml", "配置文件路径")
    flag.StringVar(&dashboardCliParam.DatebaseLocation, "db", "data/sqlite.db", "Sqlite3数据库文件路径")
    flag.Parse()

    if dashboardCliParam.Version {
        fmt.Println(singleton.Version)
        os.Exit(0)
    }

    // 初始化 dao 包
    singleton.InitConfigFromPath(dashboardCliParam.ConfigFile)
    singleton.InitTimezoneAndCache()
    singleton.InitDBFromPath(dashboardCliParam.DatebaseLocation)
    singleton.InitLocalizer()
    initSystem()

    // TODO 使用 cmux 在同一端口服务 HTTP 和 gRPC
    singleton.CleanMonitorHistory()
...
naiba commented 3 weeks ago

是的

naiba commented 3 weeks ago

与运行时无关的可以放到 init,与运行时状态有关的是要放在 main 的