//go:build linux package service import ( "fmt" "os" "os/exec" "strings" "mfd-monitor-agent/internal/config" ) var currentUID = os.Geteuid // linuxManager manages a systemd service for the agent. type linuxManager struct{} // newManager returns the Linux systemd-backed service manager. func newManager() Manager { return linuxManager{} } // Install writes a systemd unit, reloads systemd, and enables the configured service. 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" if err := os.WriteFile(path, []byte(unit), 0644); err != nil { return fmt.Errorf("write systemd unit: %w", err) } 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 builds the Linux systemd unit used by Install. func renderSystemdUnit(executable string, configPath string, cfg config.Config) string { args := []string{executable, "run"} if configPath != "" { 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 disables the service, removes its unit file, and reloads systemd. func (linuxManager) Uninstall(cfg config.Config) error { _ = 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 asks systemd to start the configured service. func (linuxManager) Start(cfg config.Config) error { return exec.Command("systemctl", "start", cfg.Service.Name).Run() } // Stop asks systemd to stop the configured service. func (linuxManager) Stop(cfg config.Config) error { return exec.Command("systemctl", "stop", cfg.Service.Name).Run() }