Golang:子进程变成僵尸



我在 Go 中有一个应用程序,它重新路由二进制文件的 STDIN 和 STDOUT,然后运行它们。简而言之,我正在做:

- create command object with the binary path (lets call the object command A) - create command object with the binary path (calling it command B) - set the stdout of command B to the stdin of Command A - start command A - start command B

我注意到每当命令 B 的进程在命令 A 运行时退出时,它就会成为进程表中的僵尸进程。

下面是一个示例:

commandA := exec.Command("samplebin")
commandB := exec.Command("sample2bin")
cmdAStdin := commandA.StdinPipe()
commandB.Stdout = cmdAStdin
commandA.Start()
commandB.Start()

如果命令 B 在命令 A 仍在运行时退出,为什么它会变成僵尸?我在 Ubuntu 14 上运行 Go 1.5。

当一个进程退出时,它总是变成僵尸,不管其他进程正在运行什么。 这就是进程终止的工作方式。 该进程将保持僵尸状态,直到其父级调用wait以获取其退出状态,或者通过忽略 SIGCHLD(可能在子进程退出之前)来指示它对子进程不感兴趣。 在此之前,它将保持僵尸状态,以免丢失退出状态。

在您的示例中,您的进程(创建进程的进程)似乎是父进程,因此 A 和 B 都将保持僵尸状态,直到您的进程收集它们。

如果进程在仍有子进程(正在运行或僵尸)时退出,则这些子进程将被重新设置为现有进程的父进程,这通常会忽略退出状态(清除僵尸)。

同意第一个答案,即退出的进程变成僵尸,直到进程被另一个进程等待。 这是我在围棋中处理事情的方式。

package main
import (
    "bytes"
    "io"
    "os"
    "os/exec"
)
func main() {
    c1 := exec.Command("samplebin")
    c2 := exec.Command("sample2bin")
    r, w := io.Pipe()
    c1.Stdout = w
    c2.Stdin = r
    var b2 bytes.Buffer
    c2.Stdout = &b2
    // Writing without a reader will deadlock so write in a goroutine
    go func() {
        // Close the writer or the pipe will not be closed for c2
        defer w.Close()
        defer c1.Wait()
        c1.Start()
    }()
    defer c2.Wait()
    c2.Start()
    io.Copy(os.Stdout, &b2)
}

最新更新