为什么apache mod_perl进程变成了僵尸?

时间:2009-12-26 17:51:11

标签: apache2 mod-perl

有时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

2 个答案:

答案 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;