Apache のグレースフル リロードが完了したことを検出する

Apache のグレースフル リロードが完了したことを検出する

Apache の graceful reload (apachectl graceful) は非同期操作のようです。スクリプトから呼び出すと、Apache が処理を実行している間もスクリプトは続行されますが、これには不確定な時間がかかる場合があります (例: 低速クライアント、長時間ダウンロード)。

リロードが完了し、Apache が新しい構成で実行されていることをプログラムで検出したいと思います。言い換えると、Apache が完了した後にのみ続行される同期呼び出しのように処理する方法を見つけたいのです。

あなたが私だったらどうしますか?

12/09 追加: Apache はアイドル スレッドを新しい構成で再起動しますが、接続が開いているスレッドは接続が終了するまで古い構成を維持するようです。したがって、Apache が新しい構成で新しい接続の受け入れを開始するタイミングを決定する方法について、より正確に質問できるかもしれません。

答え1

自分の問題は自分で解決する必要があるようです...

私が思いついた Perl のコードを紹介します。基本的には、Apache ログ ファイルの末尾を見つけて、それを記憶します。次に、Apache の再起動/再ロードを発行し、それ以降にログ ファイルに書き込まれたテキストを確認します。テキストに「通常の操作を再開しています」と記載されている場合は、再起動/再ロードが完了したと見なします。(これが本当かどうかはわかりませんが、Apache の「停止と再起動」のページからそのように思われます。http://httpd.apache.org/docs/2.2/stopping.html

改善していただければ幸いです。

my $lastPos;

sub textSinceLast {
    my $logF  = '/var/log/httpd/error_log'; # or wherever your Apache log file is

    open( FH, '<', $logF ) || die( "Cannot open $logF" );
    my $pos  = sysseek( FH, 0, SEEK_END );
    my $ret = "Still at mark";

    if( defined( $lastPos ) && $pos != $lastPos ) {
        sysseek( FH, $lastPos, SEEK_SET );
        sysread( FH, $ret, $pos - $lastPos, 0 );
    }
    close( FH );
    $lastPos = $pos;
    return $ret;
}

textSinceLast();

`systemctl reload httpd`; # or "service restart apache2", or whatever your distro wants

for( my $i=0 ; $i<1000 ; ++$i ) { # give up after 10sec
    select( undef, undef, undef, 0.01 ); # apparently a tricky way of sleeping for 10ms
    my $text = textSinceLast();
    if( $text =~ /resuming normal operations/ ) {
        print "Detected restart on $i\n";
        last;
    }
}

関連情報