通过golang程序开始杀死进程

时间:2019-01-21 11:49:57

标签: go

我有一个正在运行的守护进程,并且启动了另一个进程。为了模拟它,我现在只是“睡眠”。如果我终止了该进程,则它仍然是僵尸。如何正确清洁。

cmd := exec.Command("sleep", "500")
err := cmd.Start()
if err != nil {
    log.Fatal(err)
}
if err := cmd.Process.Kill(); err != nil {
    log.Fatal("failed to kill process: ", err)
}
time.Sleep(10000000 * time.Millisecond)

$ ps aux | grep sleep

37342 0.0 0.0 4276984 1040 s000 S + 5:09 PM 0:00.00 grep睡眠

37309 0.0 0.0 0 0 ?? Z 5:09 PM 0:00.00(睡觉)

1 个答案:

答案 0 :(得分:2)

您需要cmd.Wait()才能完成。 (通常,在Unix中,您需要等待(2)以避免泄漏僵尸。)

"os/exec"没有这个的非阻塞变体(不等同于 waitpid (2)),但是您可以在goroutine中等待:

// Start the subprocess
cmd := exec.Command("sleep", "500")
err := cmd.Start()
if err != nil {
        log.Fatal(err)
}

// Wait for it to finish
done := make(chan struct{})
go (func () {
        cmd.Wait()
        close(done)
})()

// Set a timeout
timeout := time.NewTimer(5 * time.Second)

select {
case <-done:
        fmt.Println("process completed")
        if !timeout.Stop() {
                <-timeout.C
        }
case <-timeout.C:
        fmt.Println("deadline ran out, killing process")
        if err := cmd.Process.Kill(); err != nil {
                log.Fatal("failed to kill process: ", err)
        }
        <-done
}

select的只有一个分支将被触发,并且每个分支都会进行另一分支的必要清理。在超时的情况下,进程终止后,Wait()应该立即返回,这将向“完成”通道发出信号。