启动守护程序进程但在golang

时间:2017-08-08 12:07:12

标签: go

我有两个程序

  1. 致电(2)
  2. 启动守护程序进程(服务器),如果它尚未启动,然后针对该服务器执行一些RPC
  3. 我尝试使用cmd.Run()启动(2)中的守护程序进程,但这使cmd.Run()进入(1)永远运行,可能是因为守护程序子进程延迟。

    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
    

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

    如何实现?

    总结一下,我想要达到的目标是:

    • 启动(2)中的守护进程,如果它尚未运行并使其无限期运行
    • 仅在(2)中正确启动该守护程序进程时继续
    • 从(2)干净地退出,(2)进程和守护进程之间没有任何“关系”延迟。

    修改

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

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

    这似乎不起作用。

    编辑2:

    我只删除了我附加os.Stdoutos.Stderr的两行,现在上面的内容似乎正常。

    在程序运行时,如果有stdoutstderr会很好吗?

1 个答案:

答案 0 :(得分: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("Daemon started")

    yourRPCStuff()

    if err = cmd.Process.Kill(); err != nil {
        log.Fatal("Failed to kill daemon: ", err)
    }
}