41 lines
1.3 KiB
Go
41 lines
1.3 KiB
Go
package daemon
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
"os/exec"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Spawn startet `exe daemon run` als eigenständigen Hintergrundprozess
|
||
|
|
// (eigene Session bzw. eigene Prozessgruppe, losgelöst vom Terminal), mit
|
||
|
|
// stdout/stderr in die Log-Datei logPath (pro Start neu angelegt; leer =
|
||
|
|
// verwerfen). env ist die Umgebung des Kindes (Keys, TALK_*-Overrides).
|
||
|
|
//
|
||
|
|
// Rückgabe ist ein Kanal, der genau einmal das Wait-Ergebnis liefert, wenn
|
||
|
|
// das Kind endet — der Aufrufer erkennt daran einen fehlgeschlagenen Start
|
||
|
|
// (z. B. Port belegt), ohne auf einen Timeout warten zu müssen. Endet der
|
||
|
|
// Aufrufer zuerst, läuft der Daemon weiter (das ist der Zweck).
|
||
|
|
func Spawn(exe, logPath string, env []string) (<-chan error, error) {
|
||
|
|
var logFile *os.File
|
||
|
|
if logPath == "" {
|
||
|
|
logPath = os.DevNull
|
||
|
|
}
|
||
|
|
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644)
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("Daemon-Log %s: %w", logPath, err)
|
||
|
|
}
|
||
|
|
defer logFile.Close() // das Kind hält sein eigenes Handle
|
||
|
|
|
||
|
|
cmd := exec.Command(exe, "daemon", "run")
|
||
|
|
cmd.Env = env
|
||
|
|
cmd.Stdin = nil
|
||
|
|
cmd.Stdout = logFile
|
||
|
|
cmd.Stderr = logFile
|
||
|
|
detach(cmd)
|
||
|
|
if err := cmd.Start(); err != nil {
|
||
|
|
return nil, fmt.Errorf("Daemon starten (%s daemon run): %w", exe, err)
|
||
|
|
}
|
||
|
|
exited := make(chan error, 1)
|
||
|
|
go func() { exited <- cmd.Wait() }()
|
||
|
|
return exited, nil
|
||
|
|
}
|