有时mod_perl apache进程在“top”实用程序中标记为“defunct”,这就变成了一个僵尸进程。 这是正确的行为吗? 我不得不担心吗?
我们的Perl脚本非常简单,它不会产生任何子进程。 僵尸进程很快消失了。 Apache2,Ubuntu。
我们的apache配置在这里:apache_config.txt
这是顶部的快照。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
19525 www-data 20 0 55972 25m 4684 S 10.3 2.4 0:00.32 apache2
19486 www-data 20 0 52792 21m 4120 S 1.7 2.1 0:00.05 apache2
19538 www-data 20 0 52792 21m 4120 S 1.3 2.1 0:00.04 apache2
19539 www-data 20 0 0 0 0 Z 0.7 0.0 0:00.03 apache2 <defunct>
19481 www-data 20 0 52860 21m 4016 S 0.3 2.1 0:00.05 apache2
19521 www-data 20 0 52804 21m 3824 S 0.3 2.1 0:00.08 apache2
这些是我使用的CPAN模块
CGI();
XML::LibXML();
DateTime;
DateTime::TimeZone;
Benchmark();
Data::Dump();
Devel::StackTrace();
DBD::mysql();
DBI();
LWP();
LWP::UserAgent();
HTTP::Request();
HTTP::Response();
URI::Heuristic();
MD5();
IO::String();
DateTime::Format::HTTP();
Math::BigInt();
Digest::SHA1();
top:
26252 www-data 20 0 0 0 0 Z 0.3 0.0 0:00.22 apache2 <defunct>
access.log with pid logged as the first parameter:
26252 85.124.207.173 - - [26/Dec/2009:22:16:42 +0300] "GET /cgi-bin/wimo/server/index.pl?location=gn:2761369&request=forecast&client_part=app&ver=2_0b191&client=desktop&license_type=free&auto_id=125CC6B6DAA HTTP/1.1" 200 826 0 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; GTB6.3; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
按服务器状态
记录的3个不同的僵尸进程Srv PID Acc M CPU SS Req ConnChild Slot Client VHost Request
32-0 1300 0/0/45 _ 0.00 0 0 0.0 0.00 2.29 127.0.0.1 weather_server OPTIONS * HTTP/1.0
100-0 1254 1/7/41 C 0.22 0 0 0.0 0.00 1.51 127.0.0.1 weather_server OPTIONS * HTTP/1.0
29-0 1299 0/12/78 _ 0.31 0 2 0.0 0.78 2.37 [my ip was here] weather_server GET /server-status HTTP/1.1
答案 0 :(得分:2)
我的第一个怀疑是你真的在分叉,但也许你没有意识到这一点。是否可以包含您的代码?请记住,任何system
或``调用都是分叉的。这可能很容易发生在CPAN模块内部而你没有意识到。有一些关于mod_perl和forking的有用信息(包括如何创建僵尸以及如何避免它们)here。
更新:尝试将此添加到您的配置中:
# Monitor apache server status
ExtendedStatus On
<VirtualHost 127.0.0.1:80>
<Location /server-status>
SetHandler server-status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
</VirtualHost>
然后将Allow from
更改为您的IP,然后您可以访问http://yourdomain.com/server-status并获取有关apache的摘要信息页面。当你看到一个僵尸并看看apache认为该进程正在做什么时,尝试这样做。
答案 1 :(得分:0)
我也看到了非常简单的mod_perl 2模块。我不分叉任何东西,只需将字符串写入客户端套接字然后返回OK。在我的CentOS 5.5 Linux VM中仍然会出现不存在进程,然后消失。这是我的源代码,您可以使用“telnet yourhost 843”并按ENTER键进行测试:
package SocketPolicy;
# Run: semanage port -a -t http_port_t -p tcp 843
# And add following lines to the httpd.conf
# Listen 843
# <VirtualHost _default_:843>
# PerlModule SocketPolicy
# PerlProcessConnectionHandler SocketPolicy
# </VirtualHost>
use strict;
use warnings FATAL => 'all';
use APR::Const(-compile => 'SO_NONBLOCK');
use APR::Socket();
use Apache2::ServerRec();
use Apache2::Connection();
use Apache2::Const(-compile => qw(OK DECLINED));
use constant POLICY =>
qq{<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="8080"/>
</cross-domain-policy>
\0};
sub handler {
my $conn = shift;
my $socket = $conn->client_socket();
my $offset = 0;
# set the socket to the blocking mode
$socket->opt_set(APR::Const::SO_NONBLOCK => 0);
do {
my $nbytes = $socket->send(substr(POLICY, $offset), length(POLICY) - $offset);
# client connection closed or interrupted
return Apache2::Const::DECLINED unless $nbytes;
$offset += $nbytes;
} while ($offset < length(POLICY));
my $slog = $conn->base_server()->log();
$slog->warn('served socket policy to: ', $conn->remote_ip());
return Apache2::Const::OK;
}
1;