2

It appears Apache graceful reload (apachectl graceful) is an asynchronous operation. If I invoke it from a script, the script will continue while Apache does its thing, which may take an undetermined amount of time (e.g. slow clients, long downloads).

I'd like to programmatically detect when the reload is complete and Apache is now running with the new configuration. In other words, I'd like to find some way of treating it like a synchronous call that only continues once Apache is done.

How would you do that if you were me?

Added 12/09: It appears that Apache restarts idle threads with the new configuration but threads with open connections keep the old configuration until the connection terminates. So perhaps the question could be asked more precisely about determining when Apache starts accepting new connections with the new configuration.

Oliver Salzburg
  • 87,539
  • 63
  • 263
  • 308
  • 1
    Ah, unfortunately I understand your concern. A while ago when I was building my own portable WAMP stack, I ran into a problem because of this. I wanted to create a batch-file that would let me restart Apache, but it wouldn’t work because the kill function could take a while to finish, so re-running it would usually end up happening before the previous instance was done. I ended up inserting a loop between the kill call and the start-up call to detect if Apache is still running or not. – Synetech Dec 09 '13 at 17:53

1 Answers1

2

I guess I need to solve my own problem ...

Here's a piece of Perl I came up with. Basically, I find the end of the Apache log file, and memorize it. Then I issue an Apache restart/reload, and look what text has been written to the log file since. If the text contains "resuming normal operations" I consider the restart/reload to have been completed. (I am not sure that is true, but it sounds like it from the Apache page on "Stopping and Restarting" here: http://httpd.apache.org/docs/2.2/stopping.html)

Improvements appreciated.

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;
    }
}