golang exec.Command造成很多失效的进程

时间:2017-09-19 06:33:31

标签: go pptp

我使用golang来调用pppd,然后在一段时间后将其杀死。但是我以这种方式得到了很多失效的过程。

这是我运行pppd的方式

exec.Command("sh", "-c", "pppd call vpn").CombinedOutput()

这就是我杀了它的方式。

exec.Command("sh", "-c", "pkill pppd").CombinedOutput()

然后我得到了很多这个

root     31541 23536  0 10:54 ?        00:00:00 [pppd] <defunct>
root     31929 23356  0 10:55 ?        00:00:00 [pptpgw] <defunct>
root     31933 23356  0 10:55 ?        00:00:00 [pptpcm] <defunct>
root     31940 23356  0 10:55 ?        00:00:00 [pppd] <defunct>
root     31993 23536  0 10:55 ?        00:00:00 [pptpgw] <defunct>
root     31997 23536  0 10:55 ?        00:00:00 [pptpcm] <defunct>
root     31998 23536  0 10:55 ?        00:00:00 [pppd] <defunct>
root     32012 23356  0 10:55 ?        00:00:00 [pptpgw] <defunct>
root     32016 23356  0 10:55 ?        00:00:00 [pptpcm] <defunct>
root     32017 23356  0 10:56 ?        00:00:00 [pppd] <defunct>
root     32070 23536  0 10:56 ?        00:00:00 [pptpgw] <defunct>
root     32074 23536  0 10:56 ?        00:00:00 [pptpcm] <defunct>
root     32075 23536  0 10:56 ?        00:00:00 [pppd] <defunct>
root     32083 23356  0 10:56 ?        00:00:00 [pptpgw] <defunct>
root     32087 23356  0 10:56 ?        00:00:00 [pptpcm] <defunct>
root     32089 23356  0 10:56 ?        00:00:00 [pppd] <defunct>
root     32131 23536  0 10:57 ?        00:00:00 [pptpgw] <defunct>
root     32135 23536  0 10:57 ?        00:00:00 [pptpcm] <defunct>
root     32148 23536  0 10:57 ?        00:00:00 [pppd] <defunct>
root     32160 23356  0 10:57 ?        00:00:00 [pptpgw] <defunct>
root     32164 23356  0 10:57 ?        00:00:00 [pptpcm] <defunct>
root     32165 23356  0 10:57 ?        00:00:00 [pppd] <defunct>
root     32177 23536  0 10:57 ?        00:00:00 [pptpgw] <defunct>
root     32181 23536  0 10:57 ?        00:00:00 [pptpcm] <defunct>

如何避免失效的过程。

3 个答案:

答案 0 :(得分:4)

当进程完成时会创建这些"zombie" processes,但父进程尚未通过wait系统调用读取其退出状态。

我猜你需要做的只是在你创建的每个命令结构上调用(*Cmd).Wait()。显然,这可能不像你想的那么直截了当,因为你可能不想在第一个命令上调用Wait,直到第二个命令完成为止。

编辑:正如评论中指出的那样,(*Cmd).CombinedOutput()调用(*Cmd).Run(),调用(*Cmd).Wait() ......所以上述内容是错误的。在这种情况下,真正的答案是,由于某些原因,sh不能清理,所以解决办法就是切断midle man并按照这样的方式进行调用:

exec.Command("pppd", "call", "vpn").CombinedOutput()

我会教我下次再仔细阅读文档......

答案 1 :(得分:0)

取消命令的一种更简单的方法是使用exec.CommandContext。 e.g。

ctx, cancel := context.WithCancel(context.Background())
exec.CommandContext(ctx, "pppd", "call", "vpn").CombinedOutput()

// in some other goroutine...
cancel()

也许这会解决你的僵尸问题?

答案 2 :(得分:0)

在新线程中运行子进程

go exec.Command("sh", "-c", "pppd call vpn").CombinedOutput()

杀死子进程

exec.Command("pkill", "pppd").CombinedOutput().CombinedOutput()