Add --force-update: immediate signed-update check, stage + service restart
This commit is contained in:
@@ -186,3 +186,16 @@ func Remove() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RestartIfRunning restarts the systemd unit when it is active (used after
|
||||
// a forced update staged a new binary). Reports whether a restart
|
||||
// happened. An inactive or missing unit is not an error. Needs root.
|
||||
func RestartIfRunning() (bool, error) {
|
||||
if err := exec.Command("systemctl", "is-active", "--quiet", Name+".service").Run(); err != nil {
|
||||
return false, nil // inactive or not installed
|
||||
}
|
||||
if out, err := exec.Command("systemctl", "restart", Name+".service").CombinedOutput(); err != nil {
|
||||
return false, fmt.Errorf("systemctl restart (run as root): %w (%s)", err, out)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -40,3 +40,6 @@ func Elevated() bool { return true }
|
||||
|
||||
// RelaunchElevated is unsupported on non-Windows, non-Linux platforms.
|
||||
func RelaunchElevated([]string) (int, error) { return 0, errUnsupported }
|
||||
|
||||
// RestartIfRunning is a no-op on platforms without service integration.
|
||||
func RestartIfRunning() (bool, error) { return false, nil }
|
||||
|
||||
@@ -351,3 +351,48 @@ func configuredLogFile(configPath string) string {
|
||||
}
|
||||
return values["LOG_FILE"]
|
||||
}
|
||||
|
||||
// RestartIfRunning restarts the service when it is installed and running
|
||||
// (used after a forced update staged a new binary). Reports whether a
|
||||
// restart happened. A service that is not installed or not running is not
|
||||
// an error. Needs elevation.
|
||||
func RestartIfRunning() (bool, error) {
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("connect to service manager (run as administrator): %w", err)
|
||||
}
|
||||
defer m.Disconnect()
|
||||
s, err := m.OpenService(Name)
|
||||
if err != nil {
|
||||
return false, nil // not installed
|
||||
}
|
||||
defer s.Close()
|
||||
st, err := s.Query()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("query service: %w", err)
|
||||
}
|
||||
if st.State != svc.Running && st.State != svc.StartPending {
|
||||
return false, nil
|
||||
}
|
||||
if _, err := s.Control(svc.Stop); err != nil {
|
||||
return false, fmt.Errorf("stop service: %w", err)
|
||||
}
|
||||
deadline := time.Now().Add(30 * time.Second)
|
||||
for {
|
||||
st, err = s.Query()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("query service: %w", err)
|
||||
}
|
||||
if st.State == svc.Stopped {
|
||||
break
|
||||
}
|
||||
if time.Now().After(deadline) {
|
||||
return false, fmt.Errorf("service did not stop within 30s")
|
||||
}
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
}
|
||||
if err := s.Start(); err != nil {
|
||||
return false, fmt.Errorf("start service: %w", err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user