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. 