G B*_*dal 7 apache perl zombie-process
各种Perl脚本(服务器端包含)在网站上调用具有许多功能的Perl模块. 编辑: 脚本使用use lib引用文件夹中的库.在繁忙时段,脚本(而不是库)变成僵尸并使服务器过载.
服务器列出:
319 ? Z 0:00 [scriptname1.pl] <defunct>
320 ? Z 0:00 [scriptname2.pl] <defunct>
321 ? Z 0:00 [scriptname3.pl] <defunct>
Run Code Online (Sandbox Code Playgroud)
我每个都有数百个实例.
编辑: 我们不使用fork,system或exec,除了SSI指令
<!--#exec cgi="/cgi-bin/scriptname.pl"-->
Run Code Online (Sandbox Code Playgroud)
据我所知,在这种情况下,httpd本身将是该进程的所有者.MaxRequestPerChild设置为0,不应让父进程在子进程完成之前死掉.
到目前为止,我们认为暂时暂停某些脚本有助于服务器应对已失效的进程并防止其崩溃,但僵尸进程仍然毫无疑问地形成.显然gbacon似乎与他的理论最接近事实,即服务器无法应对负载.
什么可能导致httpd放弃这些进程?是否有任何最佳做法可以防止这些情况发生?
谢谢
答: 重点是Rob.正如他所说,生成SSI的CGI脚本不会处理那些SSI.SSI的评估发生在Apache 1.3请求周期中CGI的运行之前.这是通过Apache 2.0及更高版本修复的,因此CGI可以生成SSI命令.
由于我们在Apache 1.3上运行,因此对于每个页面视图,SSI都变成了不存在的进程.虽然服务器试图清除它们但是运行任务太忙而无法成功.结果,服务器崩溃了,变得没有响应.作为一个短期解决方案,我们审查了所有SSI并将一些流程移至客户端以释放服务器资源并给予时间清理.后来我们升级到了Apache 2.2.
比最佳练习更多的创可贴,但有时你可以简单地逃脱
$SIG{CHLD} = "IGNORE";
Run Code Online (Sandbox Code Playgroud)
在大多数Unix平台上,
CHLD(有时也称为CLD)信号相对于值的特殊行为'IGNORE'.设置$SIG{CHLD}为'IGNORE'这样的平台具有在父进程未能wait()对其子进程进行处理时不创建僵尸进程的效果(即,自动获取子进程).wait()使用$SIG{CHLD}set 调用'IGNORE'通常在这样的平台上返回-1.
如果您关心子进程的退出状态,则需要通过调用wait或收集它们(通常称为"收获")waitpid.尽管这个名字令人毛骨悚然,但僵尸只是一个已退出的儿童过程,但其状态尚未获得.
如果你的Perl程序本身就是子进程变成了僵尸,那就意味着他们的父母(那些忘记你的代码的人)需要自己清理.一个过程不能阻止自己变成一个僵尸.
我刚刚看到您的评论,您正在运行 Apache 1.3,这可能与您的问题有关。
SSI 可以运行 CGI。但生成 SSI 的 CGI 脚本不会处理这些 SSI。在 Apache 1.3 请求周期中,SSI 的评估发生在 CGI 运行之前。Apache 2.0 及更高版本已修复此问题,以便 CGI 可以生成 SSI 命令。
正如我上面所建议的,尝试单独运行脚本并查看输出。他们会生成 SSI 吗?
编辑:您是否尝试过启动一个简单的 Perl CGI 脚本来简单地打印出 Hello World 类型的 HTTP 响应?
然后,如果这有效,请添加一个简单的 SSI 指令,例如
<!--#printenv -->
Run Code Online (Sandbox Code Playgroud)
看看会发生什么。
编辑2:刚刚意识到可能发生了什么。当子进程退出且未被回收时,就会出现僵尸进程。这些进程徘徊并慢慢耗尽进程表中的资源。没有父进程的进程是孤立进程。
您是否在 Perl 脚本中分叉进程?如果是这样,您是否向父级添加了 waitpid() 调用?
您在脚本中是否也得到了正确的退出?
CORE::exit(0);
Run Code Online (Sandbox Code Playgroud)