golang exec.Command 导致大量死进程
golang exec.Command cause a lot of defunct processes
我正在使用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>
如何避免死进程。
这些 "zombie" processes 是在进程完成时创建的,但父进程尚未通过 wait
系统调用读取它们的退出状态。
我想您需要做的就是对您创建的每个命令结构调用 (*Cmd).Wait()
。显然,这可能没有您喜欢的那么直接,因为您可能不想在第二个命令完成之前在第一个命令上调用 Wait
。
编辑:正如评论中指出的那样,(*Cmd).CombinedOutput()
calls (*Cmd).Run()
调用了 (*Cmd).Wait()
... 所以上面的内容是错误的。在这种情况下真正的答案是由于某种原因 sh
没有清理,所以解决方案是切断中间人并像这样进行调用:
exec.Command("pppd", "call", "vpn").CombinedOutput()
这将教会我下次更仔细地阅读文档...
取消命令的更简单方法是使用 exec.CommandContext。例如
ctx, cancel := context.WithCancel(context.Background())
exec.CommandContext(ctx, "pppd", "call", "vpn").CombinedOutput()
// in some other goroutine...
cancel()
也许这会解决您的僵尸问题?
运行 新线程中的子进程
go exec.Command("sh", "-c", "pppd call vpn").CombinedOutput()
杀死子进程
exec.Command("pkill", "pppd").CombinedOutput().CombinedOutput()
我正在使用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>
如何避免死进程。
这些 "zombie" processes 是在进程完成时创建的,但父进程尚未通过 wait
系统调用读取它们的退出状态。
我想您需要做的就是对您创建的每个命令结构调用 (*Cmd).Wait()
。显然,这可能没有您喜欢的那么直接,因为您可能不想在第二个命令完成之前在第一个命令上调用 Wait
。
编辑:正如评论中指出的那样,(*Cmd).CombinedOutput()
calls (*Cmd).Run()
调用了 (*Cmd).Wait()
... 所以上面的内容是错误的。在这种情况下真正的答案是由于某种原因 sh
没有清理,所以解决方案是切断中间人并像这样进行调用:
exec.Command("pppd", "call", "vpn").CombinedOutput()
这将教会我下次更仔细地阅读文档...
取消命令的更简单方法是使用 exec.CommandContext。例如
ctx, cancel := context.WithCancel(context.Background())
exec.CommandContext(ctx, "pppd", "call", "vpn").CombinedOutput()
// in some other goroutine...
cancel()
也许这会解决您的僵尸问题?
运行 新线程中的子进程
go exec.Command("sh", "-c", "pppd call vpn").CombinedOutput()
杀死子进程
exec.Command("pkill", "pppd").CombinedOutput().CombinedOutput()