Jon Cage
Jon Cage

Reputation: 37500

How can I reliably launch multiple DJango FCGI servers at startup?

I currently use the following script to launch my DJango FCGI servers:

#!/bin/bash
MYAPP=$1
PIDFILE=/var/run/${MYAPP}_fcgi.pid
SOCKET=/var/django/${MYAPP}/socket.sock
MANAGESCRIPT=/var/django/${MYAPP}/manage.py
# Maximum requests for a child to service before expiring
#MAXREQ=
# Spawning method - prefork or threaded
#METHOD=
# Maximum number of children to have idle
MAXSPARE=2
# Minimum number of children to have idle
MINSPARE=1
# Maximum number of children to spawn
MAXCHILDREN=3

cd "`dirname $0`"

function failure () {
  STATUS=$?;
  echo; echo "Failed $1 (exit code ${STATUS}).";
  exit ${STATUS};
}

function start_server () {
  $MANAGESCRIPT runfcgi socket=$SOCKET pidfile=$PIDFILE \
    ${MAXREQ:+maxrequests=$MAXREQ} \
    ${METHOD:+method=$METHOD} \
    ${MAXSPARE:+maxspare=$MAXSPARE} \
    ${MINSPARE:+minspare=$MINSPARE} \
    ${MAXCHILDREN:+maxchildren=$MAXCHILDREN} \
    ${DAEMONISE:+damonize=True}
  touch $SOCKET
  chown www-data:www-data $SOCKET
  chmod 755 $SOCKET
}

function stop_server () {
  if [ -f "$PIDFILE" ]
  then
    kill `cat $PIDFILE` || failure "Server was not running."
    rm $PIDFILE
  fi
}

DAEMONISE=$3

case "$2" in
  start)
    echo -n "Starting fcgi: "
    [ -e $PIDFILE ] && { echo "PID file exsts."; exit; }
    start_server || failure "starting fcgi"
    echo "Done."
    ;;
  stop)
    echo -n "Stopping fcgi: "
    [ -e $PIDFILE ] || { echo "No PID file found."; exit; }
    stop_server
    echo "Done."
    ;;
  restart)
    echo -n "Restarting fcgi: "
    [ -e $PIDFILE ] || { echo -n "No PID file found..."; }
    stop_server
    start_server || failure "restarting fcgi"
    echo "Done."
    ;;
  *)
    echo "Usage: $0 {start|stop|restart} [--daemonise]"
    ;;
esac

exit 0

Which I manually call like this:

/var/django/server.sh mysite start

This works fine but when my hosting company reboots our server it leaves me two issues:

  1. I don't have an automated way to launch multiple sites.
  2. I end up with a mysite_fcgi.pid file existing but no associated process.

So I have two questions:

  1. How can I launch a list of sites (stored in a plain text file) automatically on startup? i.e. call /var/django/server.sh mysite1 start then /var/django/server.sh myothersite start?
  2. How can I get rid of the .pid file if the process doesn't exist and attempt to start the server as normal?

Upvotes: 1

Views: 311

Answers (2)

jpic
jpic

Reputation: 33420

How can I launch a list of sites (stored in a plain text file) automatically on startup?

In general, your OS provides a file where you can hook your commands at startup. For example, arch linux uses rc.local, gentoo either /etc/local.start either /etc/local.d/*.start, debian requires you to make an init script - which is basically a script that takes "start" or "stop" as argument and lives in /etc/init.d or /etc/rc.d depending on the distribution ...

You can use some bash code as such.

for site in $(</path/to/text/file); do
    /var/django/server.sh $site start
done

How can I get rid of the .pid file if the process doesn't exist and attempt to start the server as normal?

if [[ -f $PIDFILE ]]; then # if pidfile exists
    if [[ ! -d /proc/$(<$PIDFILE)/ ]]; then # if it contains a non running proc
        unlink $PIDFILE # delete the pidfile
    fi
fi

Upvotes: 1

Burhan Khalid
Burhan Khalid

Reputation: 174642

  1. Create an init script and assign it to the appropriate runlevel.
  2. You need to implement this in your startup/init script (that you would write in step 1)

Or, use a process manager like supervisord which takes care of all your concerns.

Here is a configuration example for fcgi from supervisord.

[fcgi-program:fcgiprogramname]
command=/usr/bin/example.fcgi
socket=unix:///var/run/supervisor/%(program_name)s.sock
process_name=%(program_name)s_%(process_num)02d
numprocs=5
priority=999
autostart=true
autorestart=unexpected
startsecs=1
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
user=chrism
redirect_stderr=true
stdout_logfile=/a/path
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stderr_logfile=/a/path
stderr_logfile_maxbytes=1MB
stderr_logfile_backups
environment=A=1,B=2

Upvotes: 1

Related Questions