So at work I have a machine that runs multiple instances & versions of Apache Tomcat, some of them using different versions of Java.
I have everything configured pretty cleanly (I think) but I noticed that when I use the catalina.sh stop command from any instance, it stops ALL the instances of Tomcat.
Here is the part in catalina.sh that seems to stop all the instances even though the both Java and Tomcat configurations should be specific to just one instance:
"$_RUNJAVA" $JAVA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
org.apache.catalina.startup.Bootstrap "$@" stop
I haven't looked at the source of org.apache.catalina.startup.Bootstrap to see exactly what it does with the stop command.
Enter Tomcat's network shutdown command to the rescue: In each server.xml, the <Server> element allows two attributes: port and shutdown. It might look like this:
<Server port="8005" shutdown="SHUTDOWN">...</Server>
I modified my Tomcat shutdown script to use this network command first to make sure it kills the correct instance. Then, if the instance is still running (which hasn't happened to me yet), I use ps and grep to find the pids of all instances that were started from a particular base directory (each instance, even if it's the same version of Tomcat, has a separate base directory that it uses for its web apps and temp files).
Here is the ingredient list:
1. server.xml, containing the element
2. XSLT stylesheet to convert server.xml to a reduced XML file that contains only the port and shutdown command I need
3. xsltproc command-line tool
4. Netcat (nc) to send the shutdown command to the Tomcat shutdown port
5. Perl script to convert the reduced XML file to a shell command
Here is my XSLT file, shutdown.xslt:
<?xml version="1.0"?>
<service xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0">
<text><xsl:value-of select="Server/@shutdown"/></text>
<port><xsl:value-of select="Server/@port"/></port>
</service>
When used with xsltproc, the shutdown.xslt file generates a small XML file that looks like this:
<?xml version="1.0"?>
<service><text>
SHUTDOWN</text><port>8005</port></service>
Here is my Perl script, generate.pl:
#!/usr/bin/perl
local $/ = undef;
my $xml = <STDIN>;
my ($text) = ($xml =~ m{<text>(.*?)</text>});
my ($port) = ($xml =~ m{<port>
(.*?)</port>});
print "echo \"$text\" | nc localhost $port";
When given the reduced XML file, generate.pl produced output like this:
echo SHUTDOWN | nc localhost 8005
So putting it all together, the part of my shutdown script that reads server.xml to find the configured shutdown port and the command looks like this:
SHUTDOWN_COMMAND=`xsltproc shutdown.xslt server.xml | perl generate.pl`
$SHUTDOWN_COMMAND
And I can use the same shutdown script with any Tomcat instance without having to duplicate the shutdown port and command information.