safesight-edge/agent/internal/procctl/systemctl.go

110 lines
2.9 KiB
Go

package procctl
import (
"bytes"
"fmt"
"io"
"os/exec"
"strconv"
"strings"
"time"
)
// SystemCtlController 使用 systemctl 管理 Media Server
type SystemCtlController struct {
serviceName string
}
// NewSystemCtlController 创建 systemctl 控制器
func NewSystemCtlController(serviceName string) *SystemCtlController {
return &SystemCtlController{
serviceName: serviceName,
}
}
func (s *SystemCtlController) Enabled() bool { return s != nil }
func (s *SystemCtlController) Status() (Status, error) {
// 检查服务是否运行
cmd := exec.Command("systemctl", "is-active", "--quiet", s.serviceName)
err := cmd.Run()
if err != nil {
// 服务未运行
return Status{Running: false}, nil
}
// 获取 PID
pidCmd := exec.Command("systemctl", "show", "--property=MainPID", "--value", s.serviceName)
out, err := pidCmd.Output()
if err != nil {
return Status{Running: true}, nil // 运行但无法获取 PID
}
pid, _ := strconv.Atoi(strings.TrimSpace(string(out)))
if pid <= 0 {
return Status{Running: true}, nil
}
return Status{
Running: true,
Pid: pid,
ConfigPath: "/opt/rk3588-media-server/etc/media-server.json",
}, nil
}
func (s *SystemCtlController) Version() (string, error) {
// 直接执行 media-server --version
cmd := exec.Command("/opt/rk3588-media-server/bin/media-server", "--version")
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("get version failed: %w", err)
}
return strings.TrimSpace(string(out)), nil
}
func (s *SystemCtlController) Start(configName string) (Status, error) {
// 使用 systemctl start
cmd := exec.Command("systemctl", "start", s.serviceName)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return Status{}, fmt.Errorf("start failed: %w, stderr: %s", err, stderr.String())
}
// 等待服务启动
time.Sleep(500 * time.Millisecond)
return s.Status()
}
func (s *SystemCtlController) Stop() (Status, error) {
cmd := exec.Command("systemctl", "stop", s.serviceName)
if err := cmd.Run(); err != nil {
return Status{}, fmt.Errorf("stop failed: %w", err)
}
return Status{Running: false}, nil
}
func (s *SystemCtlController) Restart(configName string) (Status, error) {
cmd := exec.Command("systemctl", "restart", s.serviceName)
if err := cmd.Run(); err != nil {
return Status{}, fmt.Errorf("restart failed: %w", err)
}
time.Sleep(500 * time.Millisecond)
return s.Status()
}
// 二进制更新相关功能在 systemctl 模式下不支持
func (s *SystemCtlController) BinaryInfo() (BinaryUpdateResult, error) {
return BinaryUpdateResult{}, ErrNotSupported
}
func (s *SystemCtlController) UpdateBinary(r io.Reader, contentLength int64, expectedSha256 string) (BinaryUpdateResult, error) {
return BinaryUpdateResult{}, ErrNotSupported
}
func (s *SystemCtlController) RollbackBinary(backupPath string) (BinaryUpdateResult, error) {
return BinaryUpdateResult{}, ErrNotSupported
}