In my experimentation with configuring multiple virtualhosts with SSL, I stumbled upon the magic of launchd within mac os x. I use it to make a call to ifconfig when I start up to create a new loopback interface, and it works splendidly. Knowing that it would work on startup, I thought I'd apply the principles to Tomcat.
The process of setting up Tomcat as a service in Leopard is extremely simple. It goes something like this:
- Download Tomcat
- Unpack Tomcat where you want it (/usr/local/tomcat is a good spot)
- Create a lauchd plist configuration to point to the tomcat executable
- Place that configuration file someplace where launchd will find it.
- invoke launchdctl to install the new service
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>EnvironmentVariables</key>
<dict>
<key>JAVA_HOME</key>
<string>/System/Library/Frameworks/JavaVM.framework/Home</string>
</dict>
<key>Label</key>
<string>org.apache.tomcat.tomcat6</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/tomcat6/bin/catalina.sh</string>
<string>run</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceDescription</key>
<string>Tomcat 6 Server</string>
</dict>
</plist>
OK, here's what's happening. The plist defines a dictionary data structure instructing launchd how it should work. You'll see a <key> followed by a value of some sort. I'll go key by key.
- Disabled - a boolean value.
If you want to have this active, set the value to false, as it is here. If you want to disable the service without uninstalling it, just change the disabled value to true. - EnvironmentVariables - a (sub)dictionary value.
This is just a set of name value pairs defining environment variables that you might need. In our case, Tomcat needs to know what JAVA_HOME is. You can set more if you want by adding more <key> and <string> pairs - Label - a String value.
This one is really important. It needs to be a unique identifier for the launchd process. launchd keeps track of all the things it starts and stops with this Label value. Just make sure that it's unique. It's common practice to use the reverse-domain syntax that you see here (org.apache.tomcat.tomcat6). Incidentally, it's also common practice to name this plist file with the same label (org.apache.tomcat.tomcat6.plist) - ProgramArguments - an array of strings.
Think of this as what you would type at the command line. Basically, anything you can do at the command line can be placed in a ProgramArguments value. The first string in the array is the executable program that you wish to run. Anything following is an argument that you would pass to that command. In our case, this merely does the following command:/usr/local/tomcat6/bin/catalina.sh run
- RunAtLoad - boolean value.
This is what makes this a service, telling OS X that this should run when starting up. - ServiceDescription - String value.
This helps in the console to figure out what's running. It should just be some sort of description identifying the process. In this case, Tomcat 6 Server.
Launchd looks in a couple of places for these kinds of configuration files. From the man pages of launchd:
~/Library/LaunchAgents Per-user agents provided by the user.
/Library/LaunchAgents Per-user agents provided by the administrator.
/Library/LaunchDaemons System wide daemons provided by the administrator.
/System/Library/LaunchAgents Mac OS X Per-user agents.
/System/Library/LaunchDaemons Mac OS X System wide daemons.
Since I want tomcat to start up as a machine process, not a user one, I place it in /Library/LaunchDaemons. If I wanted to make it a user process, I put it in ~/Library/LaunchAgents. A couple notes about this. First, if you put your file in /Library/LaunchDaemons, the plist file needs to be owned by root. The easiest way to do this is to open Terminal and do a "sudo cp org.apache.tomcat.tomcat6.plist /Library/LaunchDaemons/". This will make root own the file so it can start up as a system process. Second, if you decide to place the file in ~/Library/LaunchAgents, you don't need root ownership, but you do need to make sure the directory exists. By default, Leopard does not have a "LaunchAgents" folder in the user Library. So, you might have to make that directory before you copy your file there.
Final step, you'll need the Terminal. It's install time.
If you placed the plist in /Library/LaunchDaemons, do this
sudo launchctl load /Library/LaunchDaemons/org.apache.tomcat.tomcat6.plist
If you placed the plist in ~/Library/LaunchAgents, do this
launchctl load ~/Library/LaunchAgents/org.apache.tomcat.tomcat6.plist
That should do it. You now have Tomcat installed as a service on Leopard.