Running Tomcat from daemontools

I’m a big fan of the daemontools server framework for quite a few reasons. For one, it’s incredibly stable. So stable, I use it to watch Apache and restart it when it crashes because daemontools never crashes. “Depend in the direction of stability” is my mantra.

Your server might crash, but daemontools will ruthlessly restart it, and since it runs from inittab, the OS will restart daemontools if it ever crashes. But, like I said, daemontools never crashes.

Another reason I love daemontools is that it does automatic logging and log rotation, so you can create as many servers you need and you don’t have to worry that the one last server you threw in there in a hurry won’t get its logs rotated, causing your hard drive to fill up.

Tomcat, on the other hand, has never been very friendly to the system administrator. It creates many different log files at once and rotates them by renaming them with date stamps; this makes it really annoying when you’re trying to tail the log files. Log messages tend to be large and span multiple lines, so it’s very hard to see what’s going on with all the noise. Killing Tomcat requires running a shell script that sends a shutdown command to a socket, completely breaking UNIX convention for no good reason.

I decided to bite the bullet and get Tomcat to run under daemontools instead, and I’ve never been happier (well, given that I’m still talking about Java here, let’s just say I’ve never been less unhappy…). Here’s how I did it:

My run script looks like this:

#!/bin/sh
exec 2>&1
exec envdir ./env setuidgid tomcat /usr/local/tomcat/bin/catalina.sh run

In my env directory I have two files that set up my environment: JAVA_HOME and CLASSPATH. JAVA_HOME contains the following:

/usr

CLASSPATH contains this (I’ll explain why in a bit):

/usr/local/tomcat/bin/tiny-formatter.jar

I had to comment out the following line at the top of tomcat/bin/setclasspath.sh to keep it from clobbering the CLASSPATH environment variable:

# First clear out the user classpath
# CLASSPATH=

Now, tiny-formatter.jar is a little hack that makes Tomcat’s logger use only one line per log message and removes the datestamp, since multilog adds one already. It contains a class file, TinyFormatter.class, generated by compiling the following source file, TinyFormatter.java:

import java.io.PrintWriter;
import java.io.StringWriter;

import java.util.logging.Formatter;
import java.util.logging.LogRecord;

public class TinyFormatter extends Formatter
{
static final String lineSep = System.getProperty(“line.separator”);

public String format(LogRecord record)
{
StringBuffer buf = new StringBuffer(180);
buf.append(record.getLevel());
buf.append(“: “);
buf.append(formatMessage(record));
buf.append(” (“);
buf.append(record.getSourceClassName());
buf.append(‘.’);
buf.append(record.getSourceMethodName());
buf.append(‘)’);
buf.append(lineSep);

Throwable throwable = record.getThrown();
if (throwable != null) {
StringWriter sink = new StringWriter();
throwable.printStackTrace(new PrintWriter(sink, true));
buf.append(sink.toString());
}

return buf.toString();
}
}

Okay, maybe it’s not so tiny. That’s Java for ‘ya.

To install this custom formatter, I edited tomcat/conf/logging.properties and replaced its contents with the following:

handlers = java.util.logging.ConsoleHandler
.handlers = java.util.logging.ConsoleHandler

java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = TinyFormatter

The run script for the daemontools logger is pretty standard:

#!/bin/sh
exec setuidgid tomcat multilog t /var/multilog/tomcat

I can now start and stop Tomcat with “svc -u /service/tomcat” and “svc -d /service/tomcat”, and restarting is the usual “svc -t /service/tomcat”. To learn all the details I’ve left out, I highly recommend reading the djb way. I’m out of time. ;)

2 thoughts on “Running Tomcat from daemontools”

  1. Tomcat is a huge PITA. I haven’t done much with it, but what I have done drove me nuts.

    Daemontools sounds a lot like svcadm on solaris… I’m not saying that’s bad, just an observation.

  2. Yeah, it is a pain. I don’t know why, but it seems like even “lightweight” Java solutions are bloated and over-engineered. The fact that standard Java logging (which Tomcat uses, of course) puts every log entry on two lines is a classic example of Java’s bigger-is-better approach to everything. Not to mention the hundred-odd-line stack traces you get when anything goes wrong.

    Daemontools rocks my world. I don’t know anything about Solaris, but the basic idea is that any simple program, even a one-line shell script, can be a service; you don’t have to “daemonize” anything yourself. All the tools are there to keep background jobs running reliably, drop privileges, control resource limits, and write to automatically rotated logs without reinventing the wheel every time. I really don’t understand why Linux distros don’t use something like Daemontools as opposed to the /etc/init.d mess. I actually write Daemontools services to keep Apache running because Daemontools is so reliable.

    That said, djb has a rather… unique… way of developing software that is very different and takes some getting used to. Some people say it’s anti-Unix, though personally I think it has more Unix nature than most Unix development these days: lots of tiny programs that work together, simple tools, pipes and filters, and all that. His track record for security is very good.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">