Go 为什么是子流程;睡眠10“;不终止吗?
我需要测试一个进程是否终止,我所拥有的只是它的pid号。为此,我测试伪文件“/proc/”是否存在 在为这个函数编写测试时,我注意到进程没有按预期终止 对于测试,我将“sleep 10”作为子进程运行,该子进程应运行10秒。启动此过程后,我轮询伪文件“/proc/”是否消失。该伪文件永远不会消失,并且不会检测到子进程的终止 测试golang游乐场的代码会重现以下问题: 我检查了流程是否已创建,pid是否正确。在检查过程时,可以看到它变成了。它并没有因此被移除 问题如下:Go 为什么是子流程;睡眠10“;不终止吗?,go,unix,Go,Unix,我需要测试一个进程是否终止,我所拥有的只是它的pid号。为此,我测试伪文件“/proc/”是否存在 在为这个函数编写测试时,我注意到进程没有按预期终止 对于测试,我将“sleep 10”作为子进程运行,该子进程应运行10秒。启动此过程后,我轮询伪文件“/proc/”是否消失。该伪文件永远不会消失,并且不会检测到子进程的终止 测试golang游乐场的代码会重现以下问题: 我检查了流程是否已创建,pid是否正确。在检查过程时,可以看到它变成了。它并没有因此被移除 问题如下: 为什么子进程不终止 如何
在操作系统级别,在任何与POSIX兼容的操作系统(Unix、Linux、Darwin等)中,已完成但尚未被上级收集的进程处于“失效”或“僵尸”状态。它仍然存在,但不能被杀死:它已经死了。它的存在正是为了让它的上级进程能够调用操作系统级别的
wait
system调用,从而能够调用操作系统级别的wait
system调用,并看到进程现在已经死了
一旦它的上级等待它,进程就会被真正删除:不再有一个僵尸进程占用该进程ID。如果您有一个/proc
文件系统,则该进程将从/proc
中消失
在Go中,调用cmd.Wait()
调用操作系统级别的Wait
调用,这就是实现这一点的方法。如果要收集此cmd.Wait()
的结果,一个好方法是通过通道发送
(如果你想产生一个长时间运行的进程,而不是等待它,你可以拒绝它,这样你就不再是它的上级了。正确执行此操作的详细信息充满了操作系统特有的窍门,例如丢弃控件TTY、设置会话、使用
procctl
或prctl
,等等。)为什么不使用cmd.Wait来等待程序退出?您必须始终对进程调用Wait
。@Volker,因为我只有pid。我没有cmd。这只是一个测试程序。对于pid,我发现测试程序是否终止的唯一等待是检查pid是否存在于“/proc/”中。但是,如果我在for
循环之前添加go cmd.wait()
,程序的行为与预期一样。子进程未标记为已失效
。
package main
import (
"fmt"
"log"
"os"
"os/exec"
"strconv"
"time"
)
func main() {
fmt.Println("Hello, playground")
cmd := exec.Command("sleep", "10")
if err := cmd.Start(); err != nil {
log.Fatal("unexpected error:", err)
}
pidStr := strconv.Itoa(cmd.Process.Pid)
log.Println("sleep pid:", pidStr)
for {
if _, err := os.Stat("/proc/" + pidStr); os.IsNotExist(err) {
log.Println("detect termination of /proc/" + pidStr)
return
}
log.Println("pgm /proc/" + pidStr + " is running")
time.Sleep(3 * time.Second)
}
}