Files
ss/internal/service/service_linux.go
2026-07-19 20:01:38 +08:00

114 lines
2.9 KiB
Go

//go:build linux
package service
import (
"fmt"
"os"
"os/exec"
"path/filepath"
)
func newPlatformManager(configDir string) (platformManager, error) {
return &linuxServiceManager{configDir: configDir}, nil
}
// linuxServiceManager manages services via systemd. Direct port of
// LinuxServiceManager in service_manager.py.
type linuxServiceManager struct {
configDir string
}
func (l *linuxServiceManager) serviceFilePath(name string) string {
return filepath.Join("/etc/systemd/system", name+".service")
}
func (l *linuxServiceManager) createServiceFile(cfg Config) error {
execStart := cfg.ExecutablePath
if cfg.Args != "" {
execStart += " " + cfg.Args
}
description := cfg.Description
if description == "" {
description = cfg.Name
}
content := fmt.Sprintf(`[Unit]
Description=%s
After=network.target
[Service]
Type=simple
ExecStart=%s
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
`, description, execStart)
servicePath := l.serviceFilePath(cfg.Name)
if err := os.WriteFile(servicePath, []byte(content), 0o644); err != nil {
return fmt.Errorf("failed to create service file: %w", err)
}
return nil
}
func (l *linuxServiceManager) Install(cfg Config) error {
if err := l.createServiceFile(cfg); err != nil {
return err
}
if out, err := exec.Command("systemctl", "daemon-reload").CombinedOutput(); err != nil {
return fmt.Errorf("failed to install service: %s", out)
}
if out, err := exec.Command("systemctl", "enable", cfg.Name).CombinedOutput(); err != nil {
return fmt.Errorf("failed to install service: %s", out)
}
if out, err := exec.Command("systemctl", "start", cfg.Name).CombinedOutput(); err != nil {
return fmt.Errorf("failed to install service: %s", out)
}
return nil
}
func (l *linuxServiceManager) Uninstall(name string) error {
exec.Command("systemctl", "stop", name).Run()
if out, err := exec.Command("systemctl", "disable", name).CombinedOutput(); err != nil {
return fmt.Errorf("failed to uninstall service: %s", out)
}
servicePath := l.serviceFilePath(name)
if _, err := os.Stat(servicePath); err == nil {
os.Remove(servicePath)
}
if out, err := exec.Command("systemctl", "daemon-reload").CombinedOutput(); err != nil {
return fmt.Errorf("failed to uninstall service: %s", out)
}
return nil
}
func (l *linuxServiceManager) Start(name string) error {
if out, err := exec.Command("systemctl", "start", name).CombinedOutput(); err != nil {
return fmt.Errorf("failed to start service: %s", out)
}
return nil
}
func (l *linuxServiceManager) Stop(name string) error {
if out, err := exec.Command("systemctl", "stop", name).CombinedOutput(); err != nil {
return fmt.Errorf("failed to stop service: %s", out)
}
return nil
}
func (l *linuxServiceManager) Restart(name string) error {
if out, err := exec.Command("systemctl", "restart", name).CombinedOutput(); err != nil {
return fmt.Errorf("failed to restart service: %s", out)
}
return nil
}