[WIP] Add restart service command for windows

This commit is contained in:
Vladimir Stoilov
2024-09-27 17:07:01 +03:00
parent 61babe2822
commit f0272766c1
5 changed files with 72 additions and 86 deletions

View File

@@ -55,10 +55,7 @@ func initialize() *service.Instance {
// Create instance.
var execCmdLine bool
instance, err := service.New(&service.ServiceConfig{
IsRunningAsService: isRunningAsService(),
DefaultRestartCommand: defaultRestartCommand,
})
instance, err := service.New(&service.ServiceConfig{})
switch {
case err == nil:
// Continue

View File

@@ -6,6 +6,7 @@ import (
"os"
"os/exec"
"os/signal"
"strings"
"syscall"
"time"
@@ -15,8 +16,6 @@ import (
"github.com/safing/portmaster/service"
)
var defaultRestartCommand = exec.Command("systemctl", "restart", "portmaster")
func run(instance *service.Instance) {
// Set default log level.
log.SetLogLevel(log.WarningLevel)
@@ -101,9 +100,34 @@ func run(instance *service.Instance) {
printStackTo(os.Stdout, "PRINTING STACK ON EXIT")
}
// Check if restart was trigger and send start service command if true.
if isRunningAsService() && instance.ShouldRestart {
_ = runServiceRestart()
}
os.Exit(instance.ExitCode())
}
func runServiceRestart() error {
// Check if user defined custom command for restarting the service.
restartCommand, exists := os.LookupEnv("PORTMASTER_RESTART_COMMAND")
// Run the service restart
if exists && restartCommand != "" {
log.Debugf(`instance: running custom restart command: "%s"`, restartCommand)
commandSplit := strings.Split(restartCommand, " ")
cmd := exec.Command(commandSplit[0], commandSplit[1:]...)
_ = cmd.Run()
} else {
cmd := exec.Command("systemctl", "restart", "portmaster")
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed run restart command: %w", err)
}
}
return nil
}
func isRunningAsService() bool {
// Get the current process ID
pid := os.Getpid()

View File

@@ -11,7 +11,6 @@ import (
"os"
"os/exec"
"os/signal"
"sync"
"syscall"
"time"
@@ -21,14 +20,6 @@ import (
"golang.org/x/sys/windows/svc/debug"
)
var (
// wait groups
runWg sync.WaitGroup
finishWg sync.WaitGroup
defaultRestartCommand = exec.Command("sc.exe", "restart", "PortmasterCore")
)
const serviceName = "PortmasterCore"
type windowsService struct {
@@ -45,13 +36,15 @@ service:
for {
select {
case <-ws.instance.Stopped():
changes <- svc.Status{State: svc.StopPending}
log.Infof("instance stopped")
break service
case c := <-changeRequests:
switch c.Cmd {
case svc.Interrogate:
changes <- c.CurrentStatus
case svc.Stop, svc.Shutdown:
log.Debugf("received shutdown command")
changes <- svc.Status{State: svc.StopPending}
ws.instance.Shutdown()
default:
log.Errorf("unexpected control request: #%d", c)
@@ -59,9 +52,6 @@ service:
}
}
// wait until everything else is finished
// finishWg.Wait()
log.Shutdown()
// send stopped status
@@ -75,11 +65,13 @@ service:
func run(instance *service.Instance) error {
log.SetLogLevel(log.WarningLevel)
_ = log.Start()
// check if we are running interactively
isService, err := svc.IsWindowsService()
if err != nil {
return fmt.Errorf("could not determine if running interactively: %s", err)
}
// select service run type
svcRun := svc.Run
if !isService {
@@ -88,41 +80,20 @@ func run(instance *service.Instance) error {
go registerSignalHandler(instance)
}
runWg.Add(1)
// run service client
go func() {
sErr := svcRun(serviceName, &windowsService{
instance: instance,
})
if sErr != nil {
log.Infof("shuting down service with error: %s", sErr)
} else {
log.Infof("shuting down service")
}
runWg.Done()
}()
sErr := svcRun(serviceName, &windowsService{
instance: instance,
})
if sErr != nil {
fmt.Printf("shuting down service with error: %s", sErr)
} else {
fmt.Printf("shuting down service")
}
// finishWg.Add(1)
// run service
// go func() {
// // run slightly delayed
// time.Sleep(250 * time.Millisecond)
// if err != nil {
// fmt.Printf("instance start failed: %s\n", err)
// // Print stack on start failure, if enabled.
// if printStackOnExit {
// printStackTo(os.Stdout, "PRINTING STACK ON START FAILURE")
// }
// }
// runWg.Done()
// finishWg.Done()
// }()
runWg.Wait()
// Check if restart was trigger and send start service command if true.
if isRunningAsService() && instance.ShouldRestart {
_ = runServiceRestart()
}
return err
}
@@ -179,3 +150,24 @@ func isRunningAsService() bool {
}
return isService
}
func runServiceRestart() error {
// Script that wait for portmaster service status to change to stop
// and then sends a start command for the same service.
command := `
$serviceName = "PortmasterCore"
while ((Get-Service -Name $serviceName).Status -ne 'Stopped') {
Start-Sleep -Seconds 1
}
sc.exe start $serviceName`
// Create the command to execute the PowerShell script
cmd := exec.Command("powershell.exe", "-Command", command)
// Start the command. The script will continue even after the parent process exits.
err := cmd.Start()
if err != nil {
return err
}
return nil
}