I’m spent about 6 hours total working on getting multiple instance of Tomcat to run on Ubuntu and finally wrote some scripts that I’d like to share with folks. These scripts do the following:
1. Setup the box to host multiple instances (JVMs) running tomcat
This process cleans the old layout and sets up a new layout that allows for multiple instances. This includes a number of “instances” directories in /var/lib/tomcat5.5, /etc/defaults/tomat5.5 (a new directory) and /var/log/tomcat5.5.
2. Create new instances
This allows you to setup a new instance quickly. It creates all the necessary directories and also installs the new instance into the init scripts an run levels.
Things the scripts don’t do:
– Setup multiple mod_jk configurations and apache virtual hosts
– Any SSL or security management
Here’s how to use the scripts:
1. First make sure you have Java and Tomcat installed!
bash$ sudo apt-get install sun-java6-jdk tomcat5.5
2. Grab ALL of the scripts and place them in some directory (anywhere is fine)
3. Run the multiple-instances.sh script as root from the directory you put it in
bash$ sudo ./multiple-instances.sh
4. Run the new-instance.sh script to create a new instance
bash$ new-instance.sh <instance-name>
5. Configure the new server by editing the files in /var/lib/tomcat5.5/instances/<instance-name> (mainly conf/server.xml)
6. Make sure each instance has a unique port for everything including the AJP, all listeners and the container
7. Fire it up!
bash$ sudo /etc/init.d/tomcat5.5_<instance-name> start
8. Check the logs in /var/log/tomcat5.5/instances/<instance-name>/catalina.out
Due to security considerations, I’ve included the scripts inline. Any comments are welcome:
multiple-instances.sh
#!/bin/bash # Verify we are root if [ "$USER" != "root" ]; then echo "You must run this script as root" exit 1 fi # Shutdown any running instace if ! /etc/init.d/tomcat5.5 stop; then echo "Unable to stop the running tomcat instance. Please stop it before running this script." exit 1 fi # Copy over the tomcat.sh file before we change directories if [ ! -f tomcat.sh ]; then echo "The tomcat.sh file is missing. It must be in the current directory so it can be placed" echo "into the new layout" exit 1 fi cp tomcat.sh /etc/tomcat5.5 chmod go-wx /etc/tomcat5.5/tomcat.sh # Now, head out and clean up if ! cd /var/lib/tomcat5.5; then echo "You must first install tomcat from the apt repository" exit 1 fi # Make the instances layout mkdir instances chown -R tomcat55:nogroup instances chmod -R o-rwx instances chmod -R g+w instances # Clean up old layout rm work rm -rf webapps rmdir temp rmdir shared/classes rmdir shared/lib rmdir shared rm logs rm -rf conf cd /usr/share/tomcat5.5 rm conf rm logs rm shared rm temp rm work # Clean up defaults for the template script cd /etc/default/ mv tomcat5.5 tomcat-bak mkdir -p tomcat5.5/instances tomcat5.5/template mv tomcat-bak tomcat5.5/template/tomcat5.5 chown -R root:root tomcat5.5 chmod -R go-w tomcat5.5 chmod -R g+r tomcat5.5 # Clean up the logs cd /var/log/tomcat5.5 mkdir old mv * old mkdir instances chown -R tomcat55:nogroup * chmod -R o-rwx old instances chmod -R g+w old instances # Remove the old init script and turn off all script links for the run levels rm /etc/init.d/tomcat5.5 update-rc.d -f tomcat5.5 remove echo "Successfully setup the machine for multiple tomcat instances and cleaned up the single instance layout"
new-instance.sh
#!/bin/bash if [ "$USER" != "root" ]; then echo "You must run this script as root" exit 1 fi if [ $# != 1 ]; then echo "Usage: new-instance.sh " exit 1 fi # Setup the instance cd /var/lib/tomcat5.5/instances if [ -d $1 ]; then echo "Instance $1 already created." exit 1 fi mkdir $1 cd $1 mkdir conf webapps bin temp if ! cp /etc/tomcat5.5/web.xml conf; then echo "Unable to create new instance $1 because /etc/tomcat5.5/web.xml doesn't appear to exist" exit 1 fi if ! cp /etc/tomcat5.5/server.xml conf; then echo "Unable to create new instance $1 because /etc/tomcat5.5/server.xml doesn't appear to exist" exit 1 fi if ! sed "s/@INSTANCE_NAME@/$1/g" /etc/tomcat5.5/tomcat.sh > bin/tomcat.sh; then echo "Unable to find the custom tomcat.sh file in /etc/tomcat5.5. This file must exist." exit 1 fi chown -R tomcat55:nogroup /var/lib/tomcat5.5/instances/$1 chmod -R o-rwx /var/lib/tomcat5.5/instances/$1 chmod -R g+w /var/lib/tomcat5.5/instances/$1 chmod ug+rx bin/tomcat.sh # Setup the logs mkdir /var/log/tomcat5.5/instances/$1 chown -R tomcat55:nogroup /var/log/tomcat5.5/instances/$1 chmod -R o-rwx /var/log/tomcat5.5/instances/$1 chmod -R g+w /var/log/tomcat5.5/instances/$1 ln -s /var/log/tomcat5.5/instances/$1 logs # Create catalina.policy (for the security manager) echo "// This file is an example of a policy file. You can edit this file for the specific instance" > conf/catalina.policy.example echo "" >> conf/catalina.policy.example cat /etc/tomcat5.5/policy.d/*.policy >> conf/catalina.policy.example chown tomcat55:nogroup conf/catalina.policy.example chmod o-rwx conf/catalina.policy.example chmod g+w conf/catalina.policy.example # Setup auto start ln -s /var/lib/tomcat5.5/instances/$1/bin/tomcat.sh /etc/init.d/tomcat5.5_$1 update-rc.d tomcat5.5_$1 defaults 90
tomcat.sh
#!/bin/sh # # /etc/init.d/tomcat5.5 -- startup script for the Tomcat 5 servlet engine # # Written by Miquel van Smoorenburg . # Modified for Debian GNU/Linux by Ian Murdock . # Modified for Tomcat by Stefan Gybas . # ### BEGIN INIT INFO # Provides: tomcat # Required-Start: $local_fs $remote_fs $network # Required-Stop: $local_fs $remote_fs $network # Should-Start: $named # Should-Stop: $named # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start Tomcat. # Description: Start the Tomcat servlet engine. ### END INIT INFO set -e PATH=/bin:/usr/bin:/sbin:/usr/sbin NAME=tomcat5.5 DESC="Tomcat servlet engine" DAEMON=/usr/bin/jsvc CATALINA_HOME=/usr/share/$NAME INSTANCE_NAME=@INSTANCE_NAME@ DEFAULT=/etc/default/$NAME/instances/$INSTANCE_NAME . /lib/lsb/init-functions . /etc/default/rcS # The following variables can be overwritten in $DEFAULT # Run Tomcat 5 as this user ID TOMCAT5_USER=tomcat55 # The first existing directory is used for JAVA_HOME (if JAVA_HOME is not # defined in $DEFAULT) JDK_DIRS="/usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.4-sun /usr/lib/j2sdk1.4-blackdown /usr/lib/j2se/1.4 /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.3-sun /usr/lib/j2sdk1.3-blackdown /usr/lib/j2sdk1.5-ibm /usr/lib/j2sdk1.4-ibm /usr/lib/jvm/java-gcj /usr/lib/kaffe" # Directory for per-instance configuration files and webapps CATALINA_BASE=/var/lib/tomcat5.5/instances/$INSTANCE_NAME # Use the Java security manager? (yes/no) TOMCAT5_SECURITY=no # Timeout in seconds for the shutdown of all webapps TOMCAT5_SHUTDOWN=30 # End of variables that can be overwritten in $DEFAULT # overwrite settings from default file if [ -f "$DEFAULT" ]; then . "$DEFAULT" fi test -f $DAEMON || exit 0 [ -z "$TOMCAT5_USER" ] && TOMCAT5_USER=tomcat55 # Look for the right JVM to use for jdir in $JDK_DIRS; do if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then JAVA_HOME_TMP="$jdir" # checks for a real JDK like environment, needed to check if # really the java-gcj-compat-dev package is installed if [ -r "$jdir/bin/jdb" ]; then JAVA_HOME="$JAVA_HOME_TMP" fi fi done export JAVA_HOME # Set java.awt.headless=true if JAVA_OPTS is not set so the # Xalan XSL transformer can work without X11 display on JDK 1.4+ # It also looks like the default heap size of 64M is not enough for most cases # se the maximum heap size is set to 128M if [ -z "$JAVA_OPTS" ]; then JAVA_OPTS="-Djava.awt.headless=true -Xmx128M" fi JAVA_OPTS="$JAVA_OPTS -Djava.endorsed.dirs=$CATALINA_HOME/common/endorsed -Dcatalina.base=$CATALINA_BASE -Dcatalina.home=$CATALINA_HOME -Djava.io.tmpdir=$CATALINA_BASE/temp" # Set the JSP compiler if set in the tomcat5.5.default file if [ -n "$JSP_COMPILER" ]; then JAVA_OPTS="$JAVA_OPTS -Dbuild.compiler=$JSP_COMPILER" fi if [ "$TOMCAT5_SECURITY" = "yes" ]; then JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy=$CATALINA_BASE/conf/catalina.policy" fi # juli LogManager disabled if running under libgcj (see bug #395167) gcj=no "$JAVA_HOME/bin/java" -version 2>&1 | grep -q "^gij (GNU libgcj)" && gcj=yes if [ "$gcj" != "yes" ]; then JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties" fi # Define other required variables CATALINA_PID="/var/run/$NAME-$INSTANCE_NAME.pid" LOGFILE="$CATALINA_BASE/logs/catalina.out" BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar" # Look for Java Secure Sockets Extension (JSSE) JARs if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then JSSE_HOME="${JAVA_HOME}/jre/" fi export JSSE_HOME case "$1" in start) if [ -z "$JAVA_HOME" ]; then log_failure_msg "no JDK found - please set JAVA_HOME" exit 1 fi if [ ! -d "$CATALINA_BASE/conf" ]; then log_failure_msg "invalid CATALINA_BASE specified" exit 1 fi log_daemon_msg "Starting $DESC" "$NAME" if start-stop-daemon --test --start --pidfile "$CATALINA_PID" --user $TOMCAT5_USER --startas "$JAVA_HOME/bin/java" >/dev/null; then # Clean up and set permissions on required files rm -rf "$CATALINA_BASE"/temp/* chown --dereference "$TOMCAT5_USER" "$CATALINA_BASE/conf" "$CATALINA_BASE/conf/tomcat-users.xml" "$CATALINA_BASE/logs" "$CATALINA_BASE/temp" "$CATALINA_BASE/webapps" "$CATALINA_BASE/work" "$CATALINA_BASE/logs/catalina.out" || true $DAEMON -user "$TOMCAT5_USER" -cp "$JSVC_CLASSPATH" -outfile "$LOGFILE" -errfile '&1' -pidfile "$CATALINA_PID" $JAVA_OPTS "$BOOTSTRAP_CLASS" else log_progress_msg "(already running)" fi log_end_msg 0 ;; stop) log_daemon_msg "Stopping $DESC" "$NAME" if start-stop-daemon --test --start --pidfile "$CATALINA_PID" --user "$TOMCAT5_USER" --startas "$JAVA_HOME/bin/java" >/dev/null; then log_progress_msg "(not running)" else $DAEMON -cp "$JSVC_CLASSPATH" -pidfile "$CATALINA_PID" -stop "$BOOTSTRAP_CLASS" fi log_end_msg 0 ;; status) if start-stop-daemon --test --start --pidfile "$CATALINA_PID" --user $TOMCAT5_USER --startas "$JAVA_HOME/bin/java" >/dev/null; then if [ -f "$CATALINA_PID" ]; then log_success_msg "$DESC is not running, but pid file exists." exit 1 else log_success_msg "$DESC is not running." exit 3 fi else log_success_msg "$DESC is running with pid `cat $CATALINA_PID`" exit 0 fi ;; restart|force-reload) if start-stop-daemon --test --stop --pidfile "$CATALINA_PID" --user $TOMCAT5_USER --startas "$JAVA_HOME/bin/java" >/dev/null; then $0 stop sleep 1 fi $0 start ;; try-restart) if start-stop-daemon --test --start --pidfile "$CATALINA_PID" --user $TOMCAT5_USER --startas "$JAVA_HOME/bin/java" >/dev/null; then $0 start fi ;; *) log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}" exit 1 ;; esac exit 0
Great scripts, thanks. Found one small error in multiple-instances.sh:
# Clean up defaults for the template script
cd /etc/defaults/
Should be /etc/default.
. m
LikeLike
Nice catch. Updated the post to include your fix.
LikeLike
These are great. I would have had to spend more than 6 hours creating the same thing.
I only had issues with copying from the web. Maybe its just me but I get bad “, ‘, and ` characters. I also get line breaks so a continuation character ( ) would be useful. Downloadable scripts could fix these issues but I’m not concerned with the security issues.
LikeLike
Dear Sir,
That’s good you have access two instances on same machine of tomcat, but you access them on Linux or I think SUSE, but I have problem to access two liferay tomcat on same machine, I have changed port & java_home in server.xml & catalina.bat. Should I need to change another files too for it.
LikeLike
Nice scripts, thanks 🙂
Could you provide a download link though? As mentioned your blog is adding bad characters and stripping the line continuation characters.
LikeLike
I created a Google code project and open sourced these scripts. Figured it was easier this way. Here’s the place for these scripts:
http://code.google.com/p/debian-tomcat-scripts/
You can check them out from SubVersion or browse them via the web.
LikeLike
Are these scripts accurate as written for ubuntu 8.x and tomcat5.5?
Jack
LikeLike
Jack,
I’d recommend checking out the latest work I’ve done on Tomcat on Linux. I posted a DEB for running multiple instances of Tomcat 6 on Linux and it completely replaces the standard Tomcat. It also cleans up many of the messes that Debian has created with their package and is a 100% valid Tomcat installation.
Here’s the post from the Ubuntu Forums on it:
http://ubuntuforums.org/showthread.php?t=1211517
I’ll put up another blog post here about it as well.
LikeLike
Hi Brian,
Your scripts are using the older JK workers style to connect apache to tomcat. With Apache 2.2, you can also use the (easier) mod_proxy_ajp.
Is it a good suggestion if you update your scripts to this?
Marcel
LikeLike
Marcel,
If you want to join the project I’ve setup, it is located here:
http://code.google.com/p/debian-tomcat-scripts/
That project can create DEB packages and contains some more advanced scripts. Eventually I’d like to start publishing the DEBs into a valid APT repo. These scripts are also using Tomcat 6.0.x and can certainly use Apache 2.2 and mod_proxy_ajp.
Let me know if you want to help on that project.
LikeLike
Hi Brain,
I can see if i can help you with that :)… though my DEB knowledge is newby!
Some ideas:
– would be great to have the possibility to turn a manual instance into a init.d’ed instance and vice versa
– how about a t6eninstance and t6disinstance command (like a2ensite and a2dissite) which places symlinks from instances-available to a instances-enabled folder. That way, init.d/tomcat6instances can take one argument (stop/start/restart) and does that on all instances.. or takes two arguments, where 2nd is the instance name from the dir “instances-enabled”
LikeLike
Perhaps. The main difference here is that Apache is a single process where the way I have Tomcat setup is that each instance is a separate process. This was intentional in order to prevent one webapp from crashing others.
Any solution would need the ability to control single instances in cases of failures where a single instance needs to be restarted.
LikeLike
Nice work!!!
And this makes me think!!!
What if we want to run two different versions of tomcat on the same server, say 5x and 6x.
How could we manage that in case we have two different applications that one can run only with 5x and the other only with 6x?
LikeLike
That should work fine. You just need to ensure you can install both the 5.5. and 6.0 packages at the same time. This should be possible on most Linux varieties.
LikeLike
It’s the best time to make a few plans for the long run and it is time to be happy. I have read this submit and if I could I desire to suggest you some attention-grabbing issues or advice. Perhaps you can write subsequent articles relating to this article. I desire to read more issues approximately it!
LikeLike
Pretty section of content. I simply stumbled upon your website and in accession capital to say that I acquire in fact enjoyed account your weblog posts. Any way I will be subscribing in your feeds or even I achievement you access constantly fast.
LikeLike
I have written a Java based portable utility for automating the above steps for creating multiple instances. Since Java is platform independent, this utility works on all operating systems
LikeLike