//go:build linux package service import ( "fmt" "os" "os/exec" "strings" "mfd-monitor-agent/internal/config" ) // currentUID 是测试可替换的当前用户 ID 查询函数。 var currentUID = os.Geteuid // linuxManager 通过 systemd 管理 agent 服务。 type linuxManager struct{} // newManager 返回基于 Linux systemd 的服务管理器。 func newManager() Manager { return linuxManager{} } // Install 写入 systemd unit、重载 systemd 并 enable 配置的服务。 func (linuxManager) Install(executable string, cfg config.Config, opts InstallOptions) error { if currentUID() != 0 { return fmt.Errorf("install requires root") } unit := renderSystemdUnit(executable, opts.ConfigPath, cfg) path := "/etc/systemd/system/" + cfg.Service.Name + ".service" // 安装阶段写入 systemd unit,需要 root 权限且会影响系统服务注册。 if err := os.WriteFile(path, []byte(unit), 0644); err != nil { return fmt.Errorf("write systemd unit: %w", err) } // unit 文件变化后必须重载 systemd,再启用服务随系统启动。 if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil { return fmt.Errorf("systemctl daemon-reload: %w", err) } if err := exec.Command("systemctl", "enable", cfg.Service.Name).Run(); err != nil { return fmt.Errorf("systemctl enable: %w", err) } return nil } // renderSystemdUnit 生成 Install 使用的 Linux systemd unit 内容。 func renderSystemdUnit(executable string, configPath string, cfg config.Config) string { args := []string{executable, "run"} if configPath != "" { // install 接收的 -config 会固化到 ExecStart,保证服务模式读取同一配置。 args = append(args, "-config", configPath) } return fmt.Sprintf(`[Unit] Description=%s After=network-online.target Wants=network-online.target [Service] Type=simple ExecStart=%s Restart=always RestartSec=5s [Install] WantedBy=multi-user.target `, cfg.Service.Description, strings.Join(args, " ")) } // Uninstall 禁用服务、删除 unit 文件并重载 systemd。 func (linuxManager) Uninstall(cfg config.Config) error { // 服务可能已经停止或未启用,忽略 disable 错误以继续清理 unit 文件。 _ = exec.Command("systemctl", "disable", "--now", cfg.Service.Name).Run() if err := os.Remove("/etc/systemd/system/" + cfg.Service.Name + ".service"); err != nil && !os.IsNotExist(err) { return err } return exec.Command("systemctl", "daemon-reload").Run() } // Start 请求 systemd 启动配置的服务。 func (linuxManager) Start(cfg config.Config) error { return exec.Command("systemctl", "start", cfg.Service.Name).Run() } // Stop 请求 systemd 停止配置的服务。 func (linuxManager) Stop(cfg config.Config) error { return exec.Command("systemctl", "stop", cfg.Service.Name).Run() }