Wrestling with Monit and Mongrel

Many people, including myself, have had difficulty in getting Monit to properly stop and start mongrel processes. The problem stems from the fact that Monit restricts the PATH environment variable such that it does not work with the mongrel_rails cluster::* commands. I decided to investigate this issue to find a workable solution.

First I had to decide if I even wanted to use Monit. I had written a quick script that queried the status of a cluster of Mongrels through the command mongrel cluster::status and restarted any that were not running. This would have been enough except that one aspect of Monit that is useful is that it can monitor memory consumption and restart if process uses an excessive amount of memory. This is a nice feature for running Rails applications with Mongrel as memory usage can grow substantially over time. Since I was already using Monit to monitor other processes (such as Puppet) it made sense to use for as much as possible. Though I do realize that God requires far less repetition in the configuration file.

So given that I was going to use Monit to monitor my Mongrel cluster I started looking for ways to get a functional setup. It was clear that one could forgo the cluster commands and use the process commands instead. However the problem with this approach is that the ‘clean’ option, which is a requirement to restart crashed Mongrels that leave a stale PID file, is only available using the Mongrel cluster commands. So I could have written a restart command that incorporated a PID check but that seem too cumbersome. I read examples of people setting the PATH variable with the env command but I could not get that work (along with several other people apparently).

The solution I chose was to write a short script that handled the PATH setting and called the mongrel_rails command but required the minimum number of variables. I called it monitgrel:


#!/usr/bin/ruby
# monitgrel 1.0.0

def start(dir, pid)
  cmd = "/usr/local/bin/mongrel_rails cluster::start -C #{dir}/current/config/mongrel_cluster.yml --clean --only #{pid}"
  system(cmd)
end

def stop(dir, pid)
  cmd = "/usr/local/bin/mongrel_rails cluster::stop -C #{dir}/current/config/mongrel_cluster.yml --clean --only #{pid}"
  system(cmd)
end

if ARGV.length < 3
  puts "monit_helper start|stop path pid"
  exit 1
end

ENV["PATH"] = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'

case ARGV[0]
  when 'start': start(ARGV[1], ARGV[2])
  when 'stop': stop(ARGV[1], ARGV[2])
  else puts 'What?'
end

It can be called from a Monit configuration file like so:


   start program = "/usr/local/bin/monitgrel start /rails/app 3000"
    stop program = "/usr/local/bin/monitgrel  stop /rails/app 3000"

So far this is working well. Ultimately this is another hack to get around the fact that Rails is not multithreaded but in the short term it’s a good bandage.

Trackback URL for this post:

http://hightechsorcery.com/trackback/88
Creative Commons License Except where otherwise noted, content on this site is licensed under a Creative Commons by-nc-sa 3.0 License