Dear All,
A lot of newbies who have trouble starting Tomcat end up making things worse for themselves by having more than one Tomcat process running at a time. This causes endless confusion. Configuration changes are not picked up. Even killing a running Tomcat may seemingly have no effect at all, with the port still being served.
The first step is to find the Tomcat log file: catalina.out. This is the place to start in all cases of a faulty server, but I don't have to tell you that. :-) Finding this file is easy if you run with a vanilla Tomcat, you will find it in ${TOMCAT_HOME}/logs. If you use a
repackaged Tomcat you will have to check your distribution's documentation to find it.
Read the log file top to bottom, checking for an exception resembling the one below.
Code:
Jul 27, 2008 1:49:39 PM org.apache.coyote.http11.Http11Protocol init
SEVERE: Error initializing endpoint
java.net.BindException: Address already in use:8080
at org.apache.tomcat.util.net.JIoEndpoint.init(JIoEndpoint.java:501)
at org.apache.coyote.http11.Http11Protocol.init(Http11Protocol.java:176)
at org.apache.catalina.connector.Connector.initialize(Connector.java:1058)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:677)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:795)
at org.apache.catalina.startup.Catalina.load(Catalina.java:530)
at org.apache.catalina.startup.Catalina.load(Catalina.java:550)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:260)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)
What this exception is telling you is that some process is already serving port 8080. Your application server cannot bind to port 8080 to serve it because someone else already owns it. Only one process may be bound to any given port at any given time.
This is the point where I see many people trailing off into the darker parts of the UNIX woods. Mildy terrified by the prospect of having to use the command line they start to reboot their development machines to get rid of the unknown process. I am of the opinion that rebooting a machine is the computing equivalent of carpet bombing. Process assassination is more the UNIX way, and it is much faster too.
First, let's find out who is bound to port 8080 on your machine. The command to do that varies from UNIX flavour to UNIX flavour. I'll show you a few. You can click the commands shown below for their manual pages.
On FreeBSD:
Code:
% sockstat -4 -p 8080
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
kjkoster java 80929 31 tcp4 *:8080 *:*
On Mac OS X:
Code:
% lsof -i TCP:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 37801 kjkoster 11u IPv6 0xa8c44bc 0t0 TCP *:http-alt (LISTEN)
On Linux (thanks to MHSL on FreeNode's IRC channel #tomcat):
Code:
% netstat -anp | grep 8080
Proto Recv-Q Send-Q Local Address          Foreign Address        State      PID/Program name
tcp        0      0 127.0.0.1:8080        0.0.0.0:*              LISTEN      1501/jsvc.exec
On Windows, you can do it as described in
this tutorial.
This gives us the process ID of the process that is bound to port 8080. They are shown in bold in the above examples.
Given this process ID we can examine the process in more detail using the command ps. Again, the precise syntax is OS-dependent.
On FreeBSD:
Code:
% ps -wwp 80929
PID TT STAT TIME COMMAND
80929 p1 I+ 0:04.61 /usr/local/jdk1.6.0/bin/java -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=/usr/home/kjkoster/apache-tomcat-6.0.16/conf/logging.properties -Djava.endorsed.dirs=/usr/home/kjkoster/apache-tomcat-6.0.16/endorsed -classpath :/usr/home/kjkoster/apache-tomcat-6.0.16/bin/bootstrap.jar -Dcatalina.base=/usr/home/kjkoster/apache-tomcat-6.0.16 -Dcatalina.home=/usr/home/kjkoster/apache-tomcat-6.0.16 -Djava.io.tmpdir=/usr/home/kjkoster/apache-tomcat-6.0.16/temp org.apache.catalina.startup.Bootstrap start
On Mac OS X:
Code:
% ps -wwp 37801
PID TTY TIME CMD
37801 ttys000 0:04.33 /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home/bin/java -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=/Users/kjkoster/Downloads/apache-tomcat-6.0.16/conf/logging.properties -Djava.endorsed.dirs=/Users/kjkoster/Downloads/apache-tomcat-6.0.16/endorsed -classpath :/Users/kjkoster/Downloads/apache-tomcat-6.0.16/bin/bootstrap.jar -Dcatalina.base=/Users/kjkoster/Downloads/apache-tomcat-6.0.16 -Dcatalina.home=/Users/kjkoster/Downloads/apache-tomcat-6.0.16 -Djava.io.tmpdir=/Users/kjkoster/Downloads/apache-tomcat-6.0.16/temp org.apache.catalina.startup.Bootstrap start
On Linux:
Code:
% ps -fp PID
UID        PID  PPID  C STIME TTY          TIME CMD
tomcat  1501 1500  1 Jul16 ?        03:29:42 jsvc.exec -home /usr/local/java -jvm server -user tomcat -Djava.endorsed.dirs=/usr/local/apache-tomcat-6/comm
If we are happy that this process is the one that needs killing, use the kill command to end it. This is the same on all operating systems: kill <process id>.
This should help you clear out excess application servers and free up port 8080 to run your own application server on. Don't be afraid to experiment. UNIX protects the processes of other user's on your machine. So if you accidently try to kill a Tomcat from one of your co-workers, you will not do any damage to it. The kill command issues an error message and exits safely.
Earlier I said that process assasination would be faster than rebooting, but up until now you'f probably spend a couple of minutes trying out the commands. Rebooting would have been a lot faster, I'm sure. Let's tie the commands together to form a single command line that can be cut'n-pasted into a terminal.
On FreeBSD the commands tie together as shown below:
Code:
kill `sockstat -4 -p 8080 | awk '/\\*:8080/{print $3}'`
On Max OS X, it looks like this.
Code:
kill `lsof -i TCP:8080 | awk '/LISTEN/{print $2}'`
You get the picture. Constructing the command for you own distribution is left as an exercise to the reader.
Happy hunting.
Kees Jan