如何关机 Net::LDAP::Server

How to shutdown Net::LDAP::Server

我有一个基于使用的 Perl LDAP 服务器 Net::LDAP::Server 模块。 要将其 运行 作为 Linux 中的一项服务,我使用 Net::Server::PreForkSimple 图书馆。

到目前为止一切正常,但是当我关闭服务时子进程不会关闭。

关闭所有进程的正确方法是什么?

当我发送 SIGTERM 信号时,会调用 server_close 方法,但没有其他任何反应。从此,终止的子进程不再重启,但等待工作的子进程不再终止。

#!/usr/bin/perl

#chkconfig: 345 80 05
#description: LDAP Server for Innovaphone

use strict;
use warnings;

package Listener;

use Net::Server;
use base 'Net::Server::PreForkSimple';

my $continue = 1;

...

sub process_request {
    my $self = shift;

    my $in  = *STDIN{IO};
    my $out = *STDOUT{IO};

    my $sock         = $self->{server}->{client};
    my $peer_address = $sock->peerhost();
    my $peer_port    = $sock->peerport();
    logwarn( "Connection accepted from $peer_address : $peer_port" );

    my $handler = InnoLdapServer->new($sock);

    while ( 1 ) {
        my $finished = $handler->handle;
        return if $finished;
    }
}

...

sub server_close {
    logmsg( "Server close called" );
    $continue = 0;
}

# Start daemon
Proc::Daemon::Init();

my $pidfile = File::Pid->new({ file => "/var/run/inno-ldap.pid" });

if ( $pidfile->running() ) {
    die "Already running";
}

$pidfile->write();

open( STDOUT, '>', "$logpath/inno-ldap.$logName.log" ) or die "Can't open stdout log";
select( ( select( STDOUT ), $| = 1 )[0] );    # make the log file "hot" - turn off buffering

open( STDERR, '>', "$logpath/inno-ldap.$logName.error.log" ) or die "Can't open error log";
select( ( select( STDERR ), $| = 1 )[0] );    # make the log file "hot" - turn off buffering

while ( $continue ) {

    # package main;
    $roothandler = Listener->run(
        port          => [ 636, "389/tcp" ],
        proto         => "ssl",   # use ssl as the default
        ipv           => "*",     # bind both IPv4 and IPv6 interfaces
        user          => "daemon",
        group         => "daemon",
        SSL_key_file  => "/home/root/ssl_cert/server.pem",
        SSL_cert_file => "/home/root/ssl_cert/server.pem",
        max_servers   => 10,
        log_level     => 4
    );
}

$pidfile->remove();

1;

while (1) 循环更改为 process_request 中的 while ($pidfile->running()) 应该可以解决问题。将 $continue 设置为零会阻止 运行 的更多监听器,但据我所知,process_request 子例程会忽略该变量。

当然,这需要 $pidfile 提前声明,因为它不在 process_request 的范围内,因为它是在子例程定义之后声明(和分配)的。

显示的代码不处理 Net::Server 本身,即。它的 ::PreForkSimple 扩展名;如果程序被信号终止,则服务器本身需要关闭。除了上述信号外,我们看不到调用代码以及您如何“关闭服务”。

Net::Server中有一个server_close方法可以做到这一点。但是问题所指的同名方法似乎是您 Listener class 中的方法,因此它覆盖了 (grand)parent 的方法。它只会停止 child 进程中的进一步工作,不会触及服务器。

因此,如果这是在信号处理程序中调用的方法,则服务器永远不会正确关闭,并且其现有的 children 仍然存在。您需要在 Net::Server object 上调用 server_close,或者在您自己的 server_close 方法中安排调用 parent 的方法。

Process Flow下的Net::Server文档解释

During the server shutdown phase ($self->server_close), the following represents the program flow:

$self->close_children;  # if any  
$self->post_child_cleanup_hook;  
if (Restarting server) {
    $self->restart_close_hook();  
    $self->hup_server;  
}

$self->shutdown_sockets;  

$self->server_exit;

如果由于某种原因在 Net::Server object 或 Listener object 的 parent 上调用 server_close ' 然后尝试使用工作流程中列出的各个方法。

还有一些信号列在 Net::Server::PreForkSimple "personality" under Shutdown

Each of the Fork and PreFork personalities support graceful shutdowns via the QUIT signal. When a QUIT is received, the parent will signal the children and then wait for them to exit.

然后在Hot Deploy

Since version 2.000, the PreForkSimple server has accepted the TTIN and TTOU signals. When a TTIN is received, the max_servers is increased by 1. If a TTOU signal is received the max_servers is decreased by 1

但我希望关闭它不需要这个,当然不是最后一个。