Bits and Chaos

Icon

Between bits and chaos, a sysadmin stands.

Integration of Mongrel with RHEL and derivatives

(EDITED: You probably live a lot better using mod_passenger)

Mongrel is the Ruby on Rails application server. It’s not included in RHEL 4.x nor 5.x, so I wrote this little script to have it managed by the service command. If you’re used to Apache server, Mongrel is a bit different as it’s only an application server, and it’s mono-threaded. So if you want more than one instance working, you need to explicitly decides how many of them you want and on which port they will listen (one instance for one port). Mongrel works better as the back-end, on the front-end put Apache that will do a lot better work. The script I’m describing in this blog entry is for automatic starting/stopping of this instances, integration with Apache will be described in another entry.

1. Functional results

After the script installation, as root execute:

service mongrel start

to start the described (see later) RoR instances. To stop them, you can issue:

service mongrel stop

Also there are:

service mongrel status

service mongrel restart

to get the status of the servers and to restart them.

2. Instances description files

Each instance is described in a /etc/mongrel/<instancename>.conf file, which syntax is best understood by the following example:

/etc/mongrel/rubyapp.example.com.conf

# we want three instances, listening on ports 8000, 8001 and 8002
PORTS=”8000 8001 8002″

# the Rails environment (see config/database.yml of your application)
ENVIRONMENT=”production”

# the base name for the log file. Each instance will have a unique log file, as LOGFILE.PORT
LOGFILE=”/home/rubyapp.logfile”

# the basename for the pid file. Each instance will have a unique pid file, as PIDFILE.PORT
PIDFILE=”/home/rubyapp/pidfile”

# the directory containing your RoR application.
ROOTDOCUMENT=”/home/rubyapp/code”

# every other extra parameter goes there.
EXTRAPARAMS=”–user rubyapp –group rubyapp”

3. /etc/sysconfig/mongrel

This file, if exists, contains the path of the mongrel_rails application. The mongrel script assumes it as /usr/bin/mongrel_rails so if this is your case you don’t need to write any /etc/sysconfig/mongrel:

/etc/sysconfig/mongrel

#Path of mongrel_rails
MONGREL=/usr/local/bin/mongrel_rails

4. Installation of the script

Put it on /etc/init.d/mongrel, set it executable:

chown root:root /etc/init.d/mongrel

chmod ug=rwx,o=x /etc/init.d/mongrel

add it to chkconfig:

chkconfig –add mongrel

and then set it for automatic starting at appropriate runlevels:

chkconfig –level 345 mongrel on

5. The /etc/init.d/mongrel script

<pre>#!/bin/bash
#
# Mongrel      Startup script for the Mongrel Server
#
# chkconfig: - 84 10
# description: Mongrel is a Ruby on Rails application server
#
# processname: mongrel_rails
# config: /etc/sysconfig/mongrel
# instance config: /etc/mongrel/*.conf

# Source function library.
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/mongrel ]; then
        . /etc/sysconfig/mongrel
fi

# Path to the mongrel_rails server.
mongrel=${MONGREL-/usr/bin/mongrel_rails}
RETVAL=0

# For each /etc/mongrel/*.conf file that describes a Ruby on Rails application
# we instantiate the corresponding server instances (one for each port).
# We also cleare the sessions, pids, cache and sockets subdirs.
# Note that you'll hopefully get a [ OK ] line for each (instance,port) pair.
start() {
      RET=0
      for instancefile in `ls /etc/mongrel/*conf`; do
            echo -n $instancefile;

            unset PORTS ENVIRONMENT LOGFILE PIDFILE ROOTDOCUMENT EXTRAPARAMS
            . $instancefile

            for INSTANCEPORT in $PORTS; do
                  INSTANCELOG=$LOGFILE.$INSTANCEPORT
                  INSTANCEPID=$PIDFILE.$INSTANCEPORT
                  CMDLINE="-e $ENVIRONMENT --port $INSTANCEPORT --log $INSTANCELOG --pid $INSTANCEPID $EXTRAPARAMS"
                  if [ -n "$ROOTDOCUMENT" ]; then
                        for SUBDIR in "sessions" "pids" "cache" "sockets"; do
                              rm -f $ROOTDOCUMENT/tmp/$SUBDIR/* 2> /dev/null
                        done
                        (cd $ROOTDOCUMENT; daemon mongrel_rails start -d $CMDLINE)
                        RETVAL=$?
                        if [ "$RETVAL" -ne "0" ]; then
                                RET=1
                        fi
                        echo
                  fi
            done
      done
      return $RET
}

# When stopping mongrel_rails we wait a delay of 10 seconds
stop() {
	echo -n $"Stopping Mongrel"
	killproc -d 10 $mongrel
	RETVAL=$?
        # We force remove of PID files (a stopped Mongrel won't do that for us)
        for instancefile in `ls /etc/mongrel/*conf`; do
                unset PORTS ENVIRONMENT LOGFILE PIDFILE ROOTDOCUMENT EXTRAPARAMS
                . $instancefile
                for INSTANCEPORT in $PORTS; do
                        INSTANCEPID=$PIDFILE.$INSTANCEPORT
                        rm -f $INSTANCEPID 2> /dev/null
                done
        done
        echo
}

# See how we were called.
case "$1" in
  start)
	start
	;;
  stop)
	stop
	;;
  status)
        status $mongrel
	RETVAL=$?
	;;
  restart)
	stop
	start
	;;
  *)
	echo $"Usage: $prog {start|stop|restart|condrestart|reload|status|fullstatus|graceful|help|configtest}"
	exit 1
esac

exit $RETVAL

/

Advertisements

Filed under: rhel, ruby on rails, , , , , ,

2 Responses

  1. Chris says:

    Thanks veeeery much! This has made the migration to my new Fedora box a wonderful one! Now with a nice startscript and a well done instance handling, mongrel is much less a pain (but SElinux was at the beginning 😉 )

  2. I’m happy that the script has been useful. Integration with SELinux, i.e. writing a Mongrel aware policy, is in the agenda, but it’s so complex and I must study so much that it’ll takes months.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: