在Golang中启动一个守护进程,但在守护进程启动过程完成之前不继续进行。

huangapple go评论86阅读模式
英文:

Starting a daemon process but not proceeding until daemon startup process has finished in golang

问题

我有两个程序:

  1. 调用(2)
  2. 如果它还没有启动,则启动一个守护进程(服务器),然后对该服务器进行一些远程过程调用(RPC)

我尝试使用cmd.Run()在(2)中启动守护进程,但这会导致(1)中的cmd.Run()一直运行,可能是因为守护进程子进程仍在运行。

cmd := exec.Command("daemonbinary")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()

// 做其他事情,最终退出程序将不起作用

然后,我想使用cmd.Start(),但问题是我必须等待守护进程实际启动后才能继续。

如何实现这一点?

总结一下,我想要实现的目标是:

  • 如果守护进程尚未运行,则在(2)中启动守护进程并使其一直运行
  • 只有在守护进程正确启动后,才能在(2)中继续执行
  • 从(2)中干净地退出,没有任何与守护进程之间的“关系”残留。

编辑:

我尝试在一个单独的进程组中启动它:

cmd.SysProcAttr = &syscall.SysProcAttr{
    Setpgid: true,
    Pgid:    0,
}

这似乎不起作用。

编辑2:

我刚刚删除了两行代码,其中我附加了os.Stdoutos.Stderr,现在上述方法似乎可以工作。

不过,在程序运行时保留stdoutstderr会更好吗?

英文:

I have two programs

  1. Calls (2)
  2. Starts a daemon process (a server) if it's not already started and then do some RPC against that server

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:

  • start the daemon process in (2) if it's not already running and keep it running indefinitely
  • only continue in (2) when that daemon process is properly started
  • exit cleanly from (2) without any "relations" between the (2) process and the daemon process lingering.

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?

答案1

得分: 2

你描述的情况听起来像是一个进程控制系统/编排器,比如docker-composesupervisord,它可以让你在单独的进程中运行服务并检查它们的状态。

如果你坚持使用Go语言,我建议定期从守护进程的StdoutPipe中读取新内容,直到有内容出现,并根据内容采取相应的操作。但我觉得这个解决方案相当繁琐。

以下是你提供的代码的翻译:

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("守护进程已启动")

	yourRPCStuff()

	if err = cmd.Process.Kill(); err != nil {
		log.Fatal("无法终止守护进程:", err)
	}
}

希望对你有帮助!

英文:

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)
	}
}

huangapple
  • 本文由 发表于 2017年8月8日 20:07:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/45567945.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定