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 }