Taking Care of Rails Support Tasks Through Custom Daemons by Tammer Saleh

Some good demo-not-working hijinks in this one.

The speaker is from Thoughtbot (Boston Rails consulting). He gets the gold star for a very well-organized talk. He talked about practical lessons learned from developing a LDAP to ActiveRecord gateway daemon.

No standard way to do a daemon in Ruby

def daemonize
# Important
Kernel.fork and Kernel.exit
Process.setsid
Kernel.fork and Kernel.exit

# Less important
File.umask 0
Dir.chdir '/'
# Release any file descriptors
ObjectSpace.each_object(IO) {|io| io.close rescue nil}
STDIN.open('/dev/null')
STDOUT.open('/dev/null', 'a')
STDERR.open('/dev/null', 'a')
end

Or (shoot! now he tells me after I copied down all the code):

require 'daemon'
Daemons.daemonize
loop {
...
}

What you still need after require 'daemon'
– Rails. Include Rails env. Need to set AR concurrency to true
– Start/stop control. Can write Unix init script in Ruby. (Why didn’t I think of that!) In OS X you can use launchd.
– Ensure only one instance. PidFile class
– Config files. YAML
– Logging. Config log file with rollover
– Security. Use Ruby code to switch over to non-root user and group

How do you test a daemon? Spawn it before your test? Complicated, broken daemons might not die, not encapsulated. Use mocking framework.

Alternatives
– Rake tasks or script/runner
– nohup
– inted & xinetd

Final tips
– Daemonize as soon as possible
– Rescue anything that can fail
– logger.debug a lot

Leave a Reply

You must be logged in to post a comment.

gears