Starting Mongrel or Memcached with Launchd

I recently needed to create some start-up scripts for both a Mongrel cluster and a couple of Memcached servers using Launchd on a Mac. Using Lingon to generate a plist for each I went through a few versions before I came up with one that would do what I wanted. Until the final version I would constantly get an error that the launchd item had failed or was spawning to quickly and that after 9 more failures the item would be unload from Launchd.

What was causing the problem was that Launchd cannot have an item run be called as a daemon, (no using the “-d” switch when starting Memcached). Starting a cluster of Mongrels using mongrel_rails cluster::start either from a script or by calling the command directly in the Launchd item ended up with the same errors. Instead of using Mongrel_rails cluster I had to start each Mongrel individually from the plist file.

The other part of using Launchd is that it can work as a watchdog service if you use the “<key>OnDemand</key> <false/>” in the plist file. If you do use it in this manner remember to unload the Launchd item before stopping whatever your running or else Launchd will only restart the service for you. So if I need to make some changes that require me to stop Memcached or Mongrel, I need to first unload the item using either Lingon again or launchctl from the terminal and then stop the service. When the work is done I can then just load the Launchd item and the service should be backup. If you do have a problem getting your item to work make sure to set StandardOutPath and StandardErrorPath to see what your service (in my case Mongrel or Memcached) is or is not doing.

Thanks to Jean-Noël Rivasseau for sending me a copy of a working Launchd item for a basic Memcached server to help me figure out what I was doing wrong. One question that Jean-Noël had was that when using launchctl list the Memcached item was not listed, but was obviously running. Remember that there are a few different places for the plist files to be kept at and that determines who and how they are started. So if you don’t see your item listed after you’ve run the command as you try running “sudo launchctl list” instead to view jobs in /Library instead of just ~/Library.

Sample Launchd plist file for Memcached to start with 64 MB, run as www and on port 11211. This would be started when the server boots-up and Launchd would keep it running.

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple Computer//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
<key>Disabled</key>
<true/>
<key>Label</key>
<string>local.server.memcached</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/memcached</string>
<string>-m</string>
<string>64</string>
<string>-u</string>
<string>www</string>
<string>-p</string>
<string>11211</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Sample Launchd plist file for Mongrel to start two Mongrels in production, running as www on ports 3000 and 3001. This would be started when the server boots-up and Launchd would keep it running.

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple Computer//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
<key>Label</key>
<string>local.server.mongrel</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/mongrel_rails</string>
<string>start</string>
<string>-e</string>
<string>production</string>
<string>-p</string>
<string>3000</string>
<string>-P</string>
<string>log/mongrel.3000.pid</string>
<string>-c</string>
<string>/Path/To/Rails/App/</string>
<string>–user</string>
<string>www</string>
<string>–group</string>
<string>www</string>
<string>/usr/local/bin/mongrel_rails</string>
<string>start</string>
<string>-e</string>
<string>production</string>
<string>-p</string>
<string>3001</string>
<string>-P</string>
<string>log/mongrel.3001.pid</string>
<string>-c</string>
<string>/Path/To/Rails/App/</string>
<string>–user</string>
<string>www</string>
<string>–group</string>
<string>www</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

2 Comments

  1. Kristofer

    Thanks for the .plists. That’s very helpful as a starting point. I’ve run into the same conceptual barrier time and time again when moving old-time daemons over to launchd. I keep forgetting that you can’t start them up into daemon mode, or *even* background them.

    one small niggling point: Your labels aren’t standard. For example
    Label
    local.server.memcached

    should be:
    Label
    com.danga.memcached

    Posted November 27, 2007 at 9:11 pm | Permalink
  2. First, Thank you very much. This will help me a lot.

    I played with mongrel_rails start … from the command line. -P and -l do not do anything if you are not going in to daemon mode. (I’m using 1.0.1).

    I’m scared to start multiple mongrels from the same plist. I don’t understand how launchd is going to decide to do two fork/execs. So, I’m going to have a plist file for each mongrel instance.

    I think I’m going to use the chdir command of the launchd.plist to get me to the rails base. And I also think I’m going to use stdout and stderr options in the plist for the log files.

    Posted December 2, 2007 at 12:27 am | Permalink

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*