将代码与测试注释改为中文以符合仓库规范;新增中文部署指南、 示例配置,并完善构建脚本对 VERSION 注入的说明。 Co-authored-by: Cursor <cursoragent@cursor.com>
138 lines
3.6 KiB
Go
138 lines
3.6 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"flag"
|
||
"fmt"
|
||
"log/slog"
|
||
"net/http"
|
||
"os"
|
||
"os/signal"
|
||
"syscall"
|
||
"time"
|
||
|
||
"mfd-monitor-agent/internal/collector"
|
||
"mfd-monitor-agent/internal/config"
|
||
"mfd-monitor-agent/internal/httpapi"
|
||
"mfd-monitor-agent/internal/reporter"
|
||
"mfd-monitor-agent/internal/service"
|
||
"mfd-monitor-agent/internal/snapshot"
|
||
)
|
||
|
||
var version = "0.1.0"
|
||
|
||
// main 运行 CLI,命令失败时以非零状态退出。
|
||
func main() {
|
||
if err := runCLI(os.Args[1:]); err != nil {
|
||
_, _ = fmt.Fprintln(os.Stderr, err)
|
||
os.Exit(1)
|
||
}
|
||
}
|
||
|
||
// runCLI 分发 agent 子命令,并在调用处理函数前加载配置。
|
||
func runCLI(args []string) error {
|
||
if len(args) == 0 {
|
||
args = []string{"run"}
|
||
}
|
||
switch args[0] {
|
||
case "run":
|
||
fs := flag.NewFlagSet("run", flag.ExitOnError)
|
||
configPath := fs.String("config", "", "JSON 配置文件路径")
|
||
if err := fs.Parse(args[1:]); err != nil {
|
||
return err
|
||
}
|
||
cfg, err := config.Load(*configPath)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return runAgent(cfg)
|
||
case "install":
|
||
cfg, executable, configPath, err := commandConfig(args[1:])
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return service.NewManager().Install(executable, cfg, service.InstallOptions{ConfigPath: configPath})
|
||
case "uninstall":
|
||
cfg, _, _, err := commandConfig(args[1:])
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return service.NewManager().Uninstall(cfg)
|
||
case "start":
|
||
cfg, _, _, err := commandConfig(args[1:])
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return service.NewManager().Start(cfg)
|
||
case "stop":
|
||
cfg, _, _, err := commandConfig(args[1:])
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return service.NewManager().Stop(cfg)
|
||
case "version":
|
||
fmt.Println(version)
|
||
return nil
|
||
default:
|
||
return fmt.Errorf("unknown command %q; expected run, install, uninstall, start, stop, version", args[0])
|
||
}
|
||
}
|
||
|
||
// commandConfig 解析服务相关子命令的标志并解析可执行文件路径。
|
||
func commandConfig(args []string) (config.Config, string, string, error) {
|
||
fs := flag.NewFlagSet("service", flag.ExitOnError)
|
||
configPath := fs.String("config", "", "JSON 配置文件路径")
|
||
executableFlag := fs.String("exe", "", "agent 可执行文件路径(默认当前二进制)")
|
||
if err := fs.Parse(args); err != nil {
|
||
return config.Config{}, "", "", err
|
||
}
|
||
cfg, err := config.Load(*configPath)
|
||
if err != nil {
|
||
return cfg, "", "", err
|
||
}
|
||
executable := *executableFlag
|
||
if executable == "" {
|
||
executable, err = os.Executable()
|
||
if err != nil {
|
||
return cfg, "", "", err
|
||
}
|
||
}
|
||
return cfg, executable, *configPath, nil
|
||
}
|
||
|
||
// runAgent 启动采集、可选上报与本地 HTTP API,直至收到退出信号。
|
||
func runAgent(cfg config.Config) error {
|
||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||
defer stop()
|
||
|
||
startedAt := time.Now().UTC()
|
||
cache := snapshot.NewCache(collector.New(cfg.HostID), version, startedAt)
|
||
go cache.Run(ctx, cfg.Collect.Interval.Duration(), cfg.Collect.Timeout.Duration())
|
||
|
||
if cfg.Report.Enabled {
|
||
client := reporter.NewClient(cfg.Report.Endpoint, cfg.Report.Timeout.Duration())
|
||
go reporter.Run(ctx, cache, client, cfg.Report.Interval.Duration(), logger)
|
||
}
|
||
|
||
server := &http.Server{
|
||
Addr: cfg.HTTP.ListenAddress,
|
||
Handler: httpapi.New(cache),
|
||
ReadHeaderTimeout: 5 * time.Second,
|
||
}
|
||
go func() {
|
||
<-ctx.Done()
|
||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
defer cancel()
|
||
_ = server.Shutdown(shutdownCtx)
|
||
}()
|
||
|
||
logger.Info("agent listening", "address", cfg.HTTP.ListenAddress)
|
||
err := server.ListenAndServe()
|
||
if errors.Is(err, http.ErrServerClosed) {
|
||
return nil
|
||
}
|
||
return err
|
||
}
|