I have two programs
I tried to start the daemon-process in (2) with cmd.Run()
, but that left the cmd.Run()
in (1) running forever, probably because of the daemon child process lingering.
cmd := exec.Command("daemonbinary")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
// do other stuff and eventually exit the program would not work
I then figured I'd use cmd.Start()
instead, but the problem is that I have to wait for the daemon process to actually start before I can continue.
How can that be achieved?
To recap, what I want to achieve is:
Edit:
I tried starting it in a separate process group:
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
Pgid: 0,
}
this did not seem to work.
Edit 2:
I just remove two lines where I had attached os.Stdout
and os.Stderr
and now the above seems to be working.
Would be nice however to have that stdout
and stderr
while the program is running?
The situation you are describing sounds like something for an process control system/orchestrator like docker-compose
or supervisord
, which would allow you to run services in separate processes and check their state.
If you insist on staying within Go, I would suggest to read from daemon StdoutPipe
periodically for new content until it's there and act upon it. But I find this solution quite hacky.
package main
import (
"fmt"
"log"
"os/exec"
"time"
)
func main() {
cmd := exec.Command("bash", "-c", "sleep 2 && echo started && sleep 5")
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
buffer := make([]byte, 7)
for {
stdout.Read(buffer)
if string(buffer) == "started" {
break
}
time.Sleep(500 * time.Millisecond)
}
fmt.Println("Daemon started")
yourRPCStuff()
if err = cmd.Process.Kill(); err != nil {
log.Fatal("Failed to kill daemon: ", err)
}
}