golang exec.Command导致了很多僵尸进程。

huangapple go评论120阅读模式
英文:

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>

如何避免僵尸进程?

英文:

I'm using golang to call pppd and then kill it after a while. However I got a lot of defunct proccesses in this way.

This is how I run pppd

exec.Command(&quot;sh&quot;, &quot;-c&quot;, &quot;pppd call vpn&quot;).CombinedOutput()

This is how I kill it.

exec.Command(&quot;sh&quot;, &quot;-c&quot;, &quot;pkill pppd&quot;).CombinedOutput()

Then I got a lot of this

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

How can I avoid defunct processes.

答案1

得分: 10

这些“僵尸”进程是在进程结束后,父进程没有通过wait系统调用读取它们的退出状态时创建的。

我猜你只需要在每个创建的命令结构上调用(*Cmd).Wait()就可以了。显然,这可能没有你期望的那么简单,因为你可能不想在第一个命令完成之前就调用Wait

编辑:正如评论中指出的那样,(*Cmd).CombinedOutput()调用了(*Cmd).Run(),而(*Cmd).Run()又调用了(*Cmd).Wait()... 所以上面的说法是错误的。在这种情况下,真正的解决方法是由于某种原因sh没有清理干净,所以解决办法是直接调用如下命令:

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

这次我会更仔细地阅读文档了...

英文:

These "zombie" processes are created when a process has finished, but the parent has not read their exit status via the wait system call.

I would guess that all you need to do is call (*Cmd).Wait() on every command structure you create. Obviously This will be less straight forward than you may like, since you probably don't want to call Wait on the first command until after the second command is finished.


EDIT: As is pointed out in the comments, (*Cmd).CombinedOutput() calls (*Cmd).Run(), which calls (*Cmd).Wait()... So the above is wrong. The real answer in this case is that for some reason sh isn't cleaning up, and so the solution is to cut out the midle man and do the call like so:

exec.Command(&quot;pppd&quot;, &quot;call&quot;, &quot;vpn&quot;).CombinedOutput()

That'll teach me to read the docs a little closer next time...

答案2

得分: 0

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

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

// 在其他的goroutine中...
cancel()

也许这可以解决你的僵尸进程问题?

英文:

A simpler way to cancel your command would be to use exec.CommandContext. e.g.

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

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

Maybe this would solve your zombie problem?

答案3

得分: 0

在新线程中运行子进程

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

终止子进程

exec.Command("pkill", "pppd").CombinedOutput().CombinedOutput()
英文:

run subprocess in a new thread

go exec.Command(&quot;sh&quot;, &quot;-c&quot;, &quot;pppd call vpn&quot;).CombinedOutput()

kill subprocess

exec.Command(&quot;pkill&quot;, &quot;pppd&quot;).CombinedOutput().CombinedOutput()

huangapple
  • 本文由 发表于 2017年9月19日 14:33:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/46293435.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定