h1ghlevelb1ts

Java programs as daemons on Mac OS X

For a while now I am running a local instance of Nexus (Sonatype's maven proxy) and Hudson (continuous integration engine ) on my MacBook. the benefits might not be so obvious initially, but I think as developer you should familiar with the tools supporting your work, even if these tools might be provided to you by some system admin. Besides, it is sometimes quite nice to trigger a clean build of the software you are working on on your own machine while still working on your local copy.

Anyways, initially I started Nexus and Hudson (which runs in a servlet container) manually when I booted my notebook. Obviously I wanted to automate this. Coming from the Linux world I tried to find the directory /etc/init.d. Anyone who has done the same will know that this was a futile search. It became quite quickly clear to me that Mac uses a different approach for service configuration.

A search on the internet first led me down the path of StartupItems, but some more research showed the better way of doing this is to use the services of the launchd deamon. The are system and user specific services, configured in /System/Library/LaunchAgents and ~/System/Library/LaunchAgents respectively. The configuration uses Mac's plist xml format. Since I am not really used to these plist files I had a quick check on the net. surely there must be some sort of frontend to this. And yes, there is - Lingon. I am not sure how active development is on this project, but the version I downloaded did everything I wanted. The interface it quite intuitive, so there is no point to go into too much detail. Instead here comes the plist file Lingon created to for me to run Tomcat as service:

<?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">
<!-- Tomcat Startup Script -->
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>org.apache.jakarta.tomcat</string>
  <key>OnDemand</key>
  <false/>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/java/tomcat/bin/catalina.sh</string>
    <string>run</string>
  </array>
  <key>ServiceDescription</key>
  <string>Tomcat Server</string>
  <key>StandardOutPath</key>
  <string>/opt/java/tomcat/log/log.stdout</string>
  <key>StandardErrorPath</key>
  <string>/opt/java/tomcat/log.stderror</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>JAVA_HOME</key>
    <string>/System/Library/Frameworks/JavaVM.framework/Home</string>
  </dict>
</dict>
</plist>

Easy, no?

Old comments

2010-02-10Pau
Really useful tip. I was stuck with the same problem in Hudson. Thanks!