我需要测试一个进程是否终止,我所拥有的只是它的 pid 号。为此,我测试伪文件“/proc/<pid>”是否存在。
为这个函数编写一个测试,我注意到这个过程没有按预期终止。
对于测试,我将“sleep 10”作为子进程运行,它应该运行 10 秒。开始这个过程后,我轮询伪文件“/proc/<pid>”是否消失。该伪文件永远不会消失,也不会检测到子进程的终止。
测试golang playground的代码,重现问题:https : //play.golang.org/p/fb4CbXkIjh3。
我检查了该进程是否已创建,并且 pid 是否正确。在检查过程中看到它变成了<defunct>。它没有因此被删除。
问题如下:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
在操作系统层面,在任何兼容 POSIX 的操作系统(Unix、Linux、Darwin 等)中,已完成但尚未被其上级收集的进程处于“defunct”或“zombie”状态。它仍然存在,但不能被杀死:它已经死了。它的存在正是为了让它的上级——可以调用操作系统级wait系统调用的进程——可以调用操作系统级wait系统调用并看到进程现在已经死了。
一旦它的上级等待它,该进程就被真正删除了:不再有僵尸进程占用该进程 ID。如果你有一个/proc文件系统,这是进程从/proc.
在 Go 中,调用会cmd.Wait()调用操作系统级别的wait调用,因此这就是执行此操作的方法。如果您想收集 this 的结果cmd.Wait(),一个好的方法是通过一个通道发送它。
(如果你想生成一个很长的运行进程而不是等待它,你可以拒绝它,这样你就不再是它的优越者。正确执行此操作的细节充满了特定于操作系统的小玩意,例如丢弃控制 tty 、设置会话、使用procctl或prctl等。)
| 归档时间: |
|
| 查看次数: |
56 次 |
| 最近记录: |