5

我正在使用 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>

我怎样才能避免失效的进程。

4

3 回答 3

10

这些“僵尸”进程是在进程完成时创建的,但父进程尚未通过wait系统调用读取其退出状态。

我猜你需要做的就是调用(*Cmd).Wait()你创建的每个命令结构。显然,这不会像您希望的那样直接,因为您可能不想Wait在第二个命令完成之前调用第一个命令。


编辑:正如评论中指出的那样,(*Cmd).CombinedOutput()调用(*Cmd).Run(),调用(*Cmd).Wait()......所以上面是错误的。在这种情况下,真正的答案是由于某种原因sh没有清理,因此解决方案是切断中间人并像这样进行调用:

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

那会教我下次更仔细地阅读文档...

于 2017-09-19T07:19:54.927 回答
0

取消命令的更简单方法是使用exec.CommandContext。例如

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

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

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

于 2018-05-09T22:56:59.247 回答
0

在新线程中运行子进程

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

杀死子进程

exec.Command("pkill", "pppd").CombinedOutput().CombinedOutput()
于 2021-04-24T14:35:03.167 回答