Files
sing-box/experimental/boxdd/cmd_service_linux.go
T
2026-07-13 15:08:24 +08:00

103 lines
2.5 KiB
Go

package main
import (
"os/exec"
"strings"
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
"github.com/spf13/cobra"
)
const (
defaultServiceWorkingDirectory = "/var/lib/sing-box-daemon"
serviceUnitName = serviceName + ".service"
)
var commandServiceRestart = &cobra.Command{
Use: "restart",
Short: "Restart the system service",
Args: cobra.NoArgs,
Run: func(command *cobra.Command, args []string) {
err := serviceRestart()
if err != nil {
log.Fatal(E.Cause(err, "restart service"))
}
},
}
func addPlatformServiceCommands() {
commandService.AddCommand(commandServiceRestart)
}
func runSystemctl(arguments ...string) error {
output, err := exec.Command("systemctl", arguments...).CombinedOutput()
if err != nil {
message := strings.TrimSpace(string(output))
if message == "" {
return E.Cause(err, "systemctl ", strings.Join(arguments, " "))
}
return E.New("systemctl ", strings.Join(arguments, " "), ": ", message)
}
return nil
}
func serviceStart() error {
return runSystemctl("start", serviceUnitName)
}
func serviceStop() error {
installed, err := serviceInstalled()
if err != nil {
return err
}
if !installed {
log.Info("service not installed")
return nil
}
return runSystemctl("stop", serviceUnitName)
}
func serviceRestart() error {
return runSystemctl("restart", serviceUnitName)
}
func serviceInstalled() (bool, error) {
loadState, err := systemctlProperty("LoadState")
if err != nil {
return false, err
}
return loadState != "" && loadState != "not-found", nil
}
func systemctlProperty(property string) (string, error) {
output, err := exec.Command("systemctl", "show", "--property="+property, "--value", serviceUnitName).CombinedOutput()
if err != nil {
message := strings.TrimSpace(string(output))
if message == "" {
return "", E.Cause(err, "query system service")
}
return "", E.New("query system service: ", message)
}
return strings.TrimSpace(string(output)), nil
}
func serviceStatus() (*serviceStatusResult, error) {
installed, err := serviceInstalled()
if err != nil {
return nil, err
}
if !installed {
return &serviceStatusResult{exitCode: 3, description: "not installed"}, nil
}
activeState, err := systemctlProperty("ActiveState")
if err != nil {
return nil, err
}
if activeState == "active" {
return &serviceStatusResult{exitCode: 0, description: "running"}, nil
}
return &serviceStatusResult{exitCode: 2, description: "stopped"}, nil
}