Family, work and life in general.
In: Ruby
3 Jan 2008I’ve been playing a lot lately with God, a process monitoring tool written in Ruby by Tom Preston-Werner. If you run your app on either a VPS (I use Slicehost) or on a dedicated host, a monitoring tool is a must have for several reasons.
First, and most importantly, you can use it to keep an eye on your application. When things go awry (as they always do) you can have god do things like alert administrators, restart processes, and anything else you can write a script to do.
Second, you can also use god as a general process control tool. Often times you have application specific processes you want to run when the server starts up. When you have only one application per server it might make some sense to handle this with shell scripts in init.d. However, many us have multiple apps on the same server. In this environment using init.d for application specific startup scripts means letting application specific tasks leak out of the application folder and mix with the main server configuration. So, rather than creating bash scripts to handle this you can let God do it and keep these scripts where they really belong; with the application.
That said, here’s my setup..
I have God installed on the server and configured to run on startup using a bash script. My main god.conf configuration file has an entry in it for each application which calls the applications specific god\boot.rb file local to each of my applications. This file loads all of the files in the god\initializers folder which is where I store my bits of god configurations.
This set up is not perfect, but its pretty nice. I can add new applications to my VPS and configure them to work with god by adding one line to my god.conf file and restarting the service. If I really want to get tricky, I can make a Capistrano task that restarts god on each deployment. Nice!
For each application, I can split my god config into parts, allowing me to manage different monitored pieces independantly. For instance, on one application I’m watching Ferret (I know, I know), BackgroundDrb and Mongrel instances with configurations for each process in a separate file.
This setup favors one global god process which for me is handy because my VPS is low on memory. This has some tradeoffs like the fact that I only have one log file for all of my applications. However, for my use the memory is worth more than the time it takes to glance through a long log.
Here’s what I did:
sudo gem install god
Let’s go ahead and create the script:
sudo nano /etc/init.d/god
Inside the blank file place the following:
RETVAL=0
case "$1" in
start)
/usr/bin/god -P /var/run/god.pid -l /var/log/god.log
/usr/bin/god load /etc/god.conf
RETVAL=$?
;;
stop)
kill `cat /var/run/god.pid`
RETVAL=$?
;;
restart)
kill `cat /var/run/god.pid`
/usr/bin/god -P /var/run/god.pid -l /var/log/god.log
/usr/bin/god load /etc/god.conf
RETVAL=$?
;;
status)
RETVAL=$?
;;
*)
echo "Usage: god {start|stop|restart|status}"
exit 1
;;
esac
exit $RETVAL
As the init file is a shell script, it needs to have executable permissions.
We set them like so:
sudo chmod +x /etc/init.d/god
Now we have the base script prepared, we need to add it to the default run levels:
sudo /usr/sbin/update-rc.d -f god defaults
The output will be similar to this:
Adding system startup for /etc/init.d/god …
/etc/rc0.d/K20god -> ../init.d/god
/etc/rc1.d/K20god -> ../init.d/god
/etc/rc6.d/K20god -> ../init.d/god
/etc/rc2.d/S20god -> ../init.d/god
/etc/rc3.d/S20god -> ../init.d/god
/etc/rc4.d/S20god -> ../init.d/god
/etc/rc5.d/S20god -> ../init.d/god
Inside the root of your application, make a god folder and inside that folder, create another folder called initializers. Here’s what mine looks like:
$ ls god -r
god:
initializers
In the god folder, create boot.rb:
sudo nano boot.rb
Inside the blank file place the following:
# Do any global application config here, like setting up SMTP notifiers
God::Contacts::Email.message_settings = {:from => ‘god@myspiffyapp.com’}
God.contact(:email) do |c|
c.name = ‘Admin’ c.email = ‘admincellphone@whatever.com’
end
# Borrowed this from the rails source, although God.load does take wildcards
Dir[”#{File.dirname(__FILE__)}/initializers/**/*.rb”].sort.each do |f|
load(f)
end
Next, we’re going to create a global god config file. In essence, its just going to load all of our application specific god files. To start, create a god.conf file:
sudo nano /etc/god.conf
Inside the blank file place the following:
# Put an extra entry for each rails application that loads
# files from the god directory in each app.
boot_files = [”/apps/myapplication/current/god/boot.rb”]
boot_files.each do |f|
if File.exists?(f)
load(RAILS_ROOT + '/god/boot.rb')
else
p 'Can''t find config file in application directory!'
end
end
Make sure you change [”/apps/myapplication/current/god/boot.rb”] to the location of your application specific god boot file.
Now save the file.
Now we can start, stop and restart god just as with any other service:
sudo /etc/init.d/god start
sudo /etc/init.d/god stop
sudo /etc/init.d/god restart
The script will also be called on a reboot so god will automatically start.
NOTE: If you have improperly written god config files, God won’t start. So, test these in advance of deployment and keep an eye on the /var/log/god log files.
In this article we installed the God monitoring tool, configured it to run on startup, and configured it to to load application specific config files for each of our applications.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque sed felis. Aliquam sit amet felis. Mauris semper, velit semper laoreet dictum, quam diam dictum urna, nec placerat elit nisl in quam. Etiam augue pede, molestie eget, rhoncus at, convallis ut, eros. Aliquam pharetra.
6 Responses to God – Ruby Process Monitoring
Brett Rogers
February 5th, 2008 at 11:10 am
Thanks for the great walk-through!
It looks like you are trying to use RAILS_ROOT constant in your global god.conf, but it is not defined.
I just replaced that line with: load( f )
bcorrigan78
February 6th, 2008 at 10:49 am
Hey Brett – My first blog comment ever. Maybe someone IS reading this thing
Thanks very much for the comment!
Cameron Booth
February 23rd, 2008 at 5:01 pm
yep, people are reading it, it came up first for my “God Ruby” search
I’ve done basically the same setup as you have, but I think I got the init.d script from somewhere else. Here’s the thing though, my server restarted recently, and god started, but it didn’t load the conf file (eg. it seems like it didn’t run the second command in the “start”script). However, if I run it manually with “service god start” then it works fine. Any ideas? I’m wondering if I should put a “sleep 5″ in the middle there to let god have time to start up or something? Or maybe pass the god.conf file right to the god startup line somehow? Any suggestions?
Thanks in advance! Cameron
bcorrigan78
February 25th, 2008 at 8:37 am
Well then, I guess I’m going to have to write another article! Can you verify that permissions are working correctly? You should be getting a log file, can you check that for errors?
Daniel
April 4th, 2008 at 12:31 pm
I couldn’t understand some parts of this article Ruby Process Monitoring – GeneralException, but I guess I just need to check some more resources regarding this, because it sounds interesting.
Sean Brown
April 4th, 2008 at 9:17 pm
Brian, you mention specifically that you are watching both a mongrel cluster and ferret DRb for one of your sites. Any chance you could post your config file (properly sanitized, of course)? I can’t figure out how to have my mongrels try to start only after ferret DRB is already up and running. I’d love to see how you’re doing it. Thanks in advance.