upstart-supervised init script for Apache?

I want to run apache on Ubuntu 10.04, and use the nice supervision stuff in upstart (I'm not just talking about the apache init script, but proper service supervision a la daemontools - which is to say, restarting apache when it dies, things like that).

Does anyone have a running upstart config for supervising apache on ubuntu 10.04?

The Googles have been no help to me, but it could be that my google-fu is weak.


Solution 1:

Woooo!

I've written my own version that is pretty much working - with some conf file hacking, and using -D NO_DETACH.

First up, I had to set User, Group and PidFile in /etc/apache2/apache2.conf manually, rather than have them coming in from /etc/apache2/envvars. I couldn't work out a way to get those vars to be exported properly (I tried both env and export as per http://manpages.ubuntu.com/manpages/lucid/man5/init.5.html, but no good).

root@lucid:/etc/apache2# diff -u apache2.conf.orig apache2.conf
--- apache2.conf.orig   2010-09-20 13:46:33.857868534 +0930
+++ apache2.conf        2010-09-20 13:47:22.377842204 +0930
@@ -63,7 +63,7 @@
 # identification number when it starts.
 # This needs to be set in /etc/apache2/envvars
 #
-PidFile ${APACHE_PID_FILE}
+PidFile /var/run/apache2.pid

 #
 # Timeout: The number of seconds before receives and sends time out.
@@ -142,8 +142,8 @@
 </IfModule>

 # These need to be set in /etc/apache2/envvars
-User ${APACHE_RUN_USER}
-Group ${APACHE_RUN_GROUP}
+User www-data
+Group www-data

 #
 # AccessFileName: The name of the file to look for in each directory

Then, this is my working /etc/init/apache2.conf:

# apache2 - http server
#
# Apache is a web server that responds to HTTP and HTTPS requests.
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog

description "apache2 http server"

start on runlevel [2345]
stop on runlevel [!2345]

pre-start script
    mkdir -p /var/run/apache2 || true
    install -d -o www-data /var/lock/apache2 || true
    # ssl_scache shouldn't be here if we're just starting up.
    # (this is bad if there are several apache2 instances running)
    rm -f /var/run/apache2/*ssl_scache* || true
end script

# Give up if restart occurs 10 times in 30 seconds.
respawn limit 10 30

exec /usr/sbin/apache2 -D NO_DETACH
respawn

I can do start|stop|status|reload apache2 and get meaningful results; if I kill -9 the master apache process, it gets respawned pretty much immediately, and it starts and stops on boot as expected. So it's working reasonably well I reckon.


There were things I tried that I could not get working.

  • Tried to remove -D NO_DETACH, in conjunction with:
expect fork
expect daemon

That failed to start the service.

  • Tried to use a similar method to /etc/apache2/envvars to populate the ${APACHE_*} variables:
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
export APACHE_PID_FILE=/var/run/apache2.pid

That failed to start, and produced an error about apache2: bad user name ${APACHE_RUN_USER}.

  • Tried console output and console default options; at this point I was really just flailing about trying to get meaningful error messages. Seemed to make no difference.

    console output

  • This was useful for debugging apache messages:

    exec /usr/sbin/apache2 -X -e debug -E /var/log/apache2/foo.log

  • This was another attempt to not modify /etc/apache2/apache2.conf that failed:

    exec APACHE_RUN_USER=www-data APACHE_RUN_GROUP=www-data APACHE_PID_FILE=/var/run/apache2.pid /usr/sbin/apache2 -D NO_DETACH -e debug -E /var/log/apache2/foo.log

Solution 2:

Well, this script worked for me:

# apache2 - http server
#
# Apache is a web server that responds to HTTP and HTTPS requests.
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog

description "apache2 http server"

start on runlevel [2345]
stop on runlevel [!2345]

pre-start script
    mkdir -p /var/run/apache2 || true
    install -d -o www-data /var/lock/apache2 || true
    # ssl_scache shouldn't be here if we're just starting up.
    # (this is bad if there are several apache2 instances running)
    rm -f /var/run/apache2/*ssl_scache* || true
end script

limit cpu 300 300
env APACHE_RUN_USER=www-data
env APACHE_RUN_GROUP=www-data
env APACHE_PID_FILE=/var/run/apache2.pid

# Give up if restart occurs 10 times in 30 seconds.
respawn limit 10 30

exec /usr/sbin/apache2 -D NO_DETACH
respawn

Solution 3:

I've also hit this problem, however I used another approach. The easiest way to get the env variables is using the source command and pointing it to the apache envvars file, then you can run apache with the -D FOREGROUND options

so basically you need a script which looks like this (mine is in /etc/apache2/apache2_foreground.sh ) :

#!/bin/bash

read pid cmd state ppid pgrp session tty_nr tpgid rest < /proc/self/stat
trap "kill -TERM -$pgrp; exit" EXIT TERM KILL SIGKILL SIGTERM SIGQUIT


source /etc/httpd/envvars
apache2 -D FOREGROUND

Then you make it executable and point the supervisor to its location, you also need to use the stopsignal 6

command=/etc/apache2/apache2_foreground.sh
stopsignal=6

The two first lines in the script catch the process group ID of the script, and set a trap which runs on signals passed to the process - this trap executes a kill with a negative process ID of the parent that runs all apache2 processes (the script itself) - killing with a negative PID means to kill all the children of such process aswell (so in this case all apache2 processes), without that I wasn't able to make supervisor kill the apache2 processes

The stopsignal 6 is used as I couldn't fin any other signal that could invoke the trap, the 9 cannot be caught, and 2 and 3 don't do anything (the script isn't killed)

after that it should work smoothly, with no modifications to the apache2 configuration whatsoever