6 posts categorized "tomcat admin"

05/12/2009

Tomcat Management: Using the JMXProxy

One hidden gem bundled with the Tomcat Manager is the JMXProxy, which allows you to do a whole bunch of cool and frightening things with your tomcat container and running applications. It is enabled by default once the Tomcat Manager is enabled. You'll need more than a browser to interact with it, however, because simply loading http://localhost:8080/manager/jmxproxy dumps everything in regular text, which is useful for getting MBean names.

Below are some groovy scripts that will highlight some of the interesting things you can get from the JMXProxy.

Get Tomcat Thread Pool

#!/usr/bin/env groovy 

package groovyx.net.http
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.TEXT

def http = new HTTPBuilder( 'http://localhost:8080/manager/jmxproxy/?qry=*:type=ThreadPool,name=http-8080' )
http.request( GET,TEXT ) { req ->
http.auth.basic( 'tomcat', 'tomcat' )
headers.'User-Agent' = 'GroovyHTTPBuilderTest/0.4'

response.success = { resp, reader ->
println "-----Response-----"
println System.out << reader
println "\n------------------"
}
response.failure = { resp ->
println "Something bad happened. ${resp.statusLine}"
}
}
The script above will print out some useful stats regarding Thread Pool statistics on the HTTP connector. Output looks something like the following:
-----Response-----
OK - Number of results: 1

Name: Catalina:type=ThreadPool,name=http-8080
modelerType: org.apache.tomcat.util.modeler.BaseModelMBean
maxThreads: 40
backlog: 100
currentThreadsBusy: 1
acceptorThreadCount: 1
threadPriority: 5
paused: false
port: 8080
tcpNoDelay: true
soLinger: -1
soTimeout: 20000
daemon: true
running: true
currentThreadCount: 6
name: http-8080

org.codehaus.groovy.runtime.FlushingStreamWriter@2580b3

------------------
Are you interested in connector-related statistics? Well, the following script will provide all the useful statistics exposed by the HTTP Connector.

Get Tomcat Connector Statistics

#!/usr/bin/env groovy 

package groovyx.net.http
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.TEXT

def http = new HTTPBuilder( 'http://localhost:8080/manager/jmxproxy/?qry=*:type=Connector,port=8080' )
http.request( GET,TEXT ) { req ->
http.auth.basic( 'tomcat', 'tomcat' )
headers.'User-Agent' = 'GroovyHTTPBuilderTest/0.4'

response.success = { resp, reader ->
println "-----Response-----"
println System.out << reader
println "\n------------------"
}
response.failure = { resp ->
println "Something bad happened. ${resp.statusLine}"
}
}
Output will look similar to the following:
-----Response-----
OK - Number of results: 1

Name: Catalina:type=Connector,port=8080
modelerType: org.apache.catalina.mbeans.ConnectorMBean
connectionUploadTimeout: 300000
keepAliveTimeout: -1
protocol: HTTP/1.1
maxThreads: 40
acceptCount: 100
connectionTimeout: 20000
connectionLinger: -1
scheme: http
port: 8080
tcpNoDelay: true
xpoweredBy: false
compression: off
maxHttpHeaderSize: 8192
proxyPort: 0
secure: false
maxPostSize: 2097152
redirectPort: 8443
bufferSize: 2048
emptySessionPath: false
threadPriority: 5
useBodyEncodingForURI: false
protocolHandlerClassName: org.apache.coyote.http11.Http11Protocol
enableLookups: false
allowTrace: false
maxKeepAliveRequests: 100
disableUploadTimeout: true

org.codehaus.groovy.runtime.FlushingStreamWriter@2580b3

------------------

List Running Servlets

#!/usr/bin/env groovy 


package groovyx.net.http
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.TEXT

def http = new HTTPBuilder( 'http://localhost:8080/manager/jmxproxy/?qry=*:j2eeType=Servlet,*' )
http.request( GET,TEXT ) { req ->
http.auth.basic( 'tomcat', 'tomcat' )
headers.'User-Agent' = 'GroovyHTTPBuilderTest/0.4'

response.success = { resp, reader ->
println "-----Response-----"
println System.out << reader
println "\n------------------"
}
response.failure = { resp ->
println "Something bad happened. ${resp.statusLine}"
}
}
There is an awful lot of output for this one so I will not be including the output for this particular script in this article.

Don't assume that interaction with the jmxproxy is all 'getting' and no 'setting'. This article dealt with the cool things you can do with the jmxproxy—the next one will deal with the frightening things.

05/08/2009

Tomcat Management: Use Groovy to Interact with Tomcat Manager

With the Tomcat Manager enabled, you can script a whole bunch of interesting ways to interact with your tomcat server. I've been using the HTTPBuilder module for Groovy a lot lately to get certain statistics from my Tomcat Manager enabled Tomcat servers. Below are some examples.

The first example is a basic script that gets ServerInfo from tomcat. It, and the following scripts, also demonstrate how to pass basic authentication over http requests with HTTPBuilder.

Get Tomcat ServerInfo Script

#!/usr/bin/env groovy 


package groovyx.net.http
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.TEXT

def http = new HTTPBuilder( 'http://localhost:8080/manager/serverinfo' )
http.request( GET,TEXT ) { req ->
http.auth.basic( 'tomcat', 'tomcat' )
headers.'User-Agent' = 'GroovyHTTPBuilderTest/0.4'

response.success = { resp, reader ->
println "-----Response-----"
println System.out << reader
println "\n------------------"
}
response.failure = { resp ->
println "Something bad happened. ${resp.statusLine}"
}
}
Output will look similar to the following:
-----Response-----
OK - Server info
Tomcat Version: Apache Tomcat/6.0.18
OS Name: Mac OS X
OS Version: 10.5.6
OS Architecture: i386
JVM Version: 1.5.0_16-b06-284
JVM Vendor: Apple Inc.
org.codehaus.groovy.runtime.FlushingStreamWriter@2580b3

------------------
A second example will list all running applications.

Script to List All Running Applications

#!/usr/bin/env groovy 


package groovyx.net.http
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.TEXT

def http = new HTTPBuilder( 'http://localhost:8080/manager/list')
http.request( GET,TEXT ) { req ->
http.auth.basic( 'tomcat', 'tomcat' )
headers.'User-Agent' = 'GroovyHTTPBuilderTest/0.4'

response.success = { resp, reader ->
println "-----Response-----"
println System.out << reader
println "\n------------------"
}
response.failure = { resp ->
println "Something bad happened. ${resp.statusLine}"
}
}
Output will look similar to the following:
-----Response-----
OK - Listed applications for virtual host localhost
/lenya:running:0:lenya
/examples:running:0:examples
/host-manager:running:0:host-manager
/docs:running:0:docs
/:running:0:ROOT
/manager:running:6:manager
org.codehaus.groovy.runtime.FlushingStreamWriter@2580b3

------------------

This final example polls the tomcat manager for a specific application, (in this case the /manager application) to report on session activity.

Script to Get Tomcat Session Info

#!/usr/bin/env groovy 


package groovyx.net.http
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.TEXT

def http = new HTTPBuilder( 'http://localhost:8080/manager/sessions?path=/manager')
http.request( GET,TEXT ) { req ->
http.auth.basic( 'tomcat', 'tomcat' )
headers.'User-Agent' = 'GroovyHTTPBuilderTest/0.4'

response.success = { resp, reader ->
println "-----Response-----"
println System.out << reader
println "\n------------------"
}
response.failure = { resp ->
println "Something bad happened. ${resp.statusLine}"
}
}
Output will look similar to the following:
-----Response-----
OK - Session information for application at context path /manager
Default maximum session inactive interval 30 minutes
<1 minutes:1 sessions
1 - <2 minutes:2 sessions
4 - <5 minutes:1 sessions
11 - <12 minutes:1 sessions
>=30 minutes:1 sessions
org.codehaus.groovy.runtime.FlushingStreamWriter@2580b3

------------------
The next article in this series will discuss another hidden gem inside of Tomcat Manager: The JMXProxy.

05/06/2009

Tomcat Management: Setting up the Tomcat Manager Application

The Tomcat Manager is a useful application bundled into tomcat 5.5 and tomcat 6. Although it is deployed by default in the tomcat distribution that can be downloaded from the Apache Software Foundation, access to it is disabled by default primarily because the functionality that it provides can be dangerous.

This article will provide instructions on how to enable it, show some of the interesting things you can do with it, and how to secure it so that it can not be accessed by untrusted sources. Since Tomcat 6.0.18 is the latest version of tomcat at the time of this writing, I will be using Tomcat 6 for all examples in this article.

Enabling Access to the Tomcat Manager

As I previously mentioned, the Tomcat Manager application is deployed by default but access to it is not enabled to anyone in a standard Tomcat 6 distribution. If you are working with a newly downloaded binary installation of Tomcat 6, go to $CATALINA_HOME/conf ($CATALINA_HOME is a variable pointing to the tomcat base installation directory, i.e. /usr/local/tomcat) and make a backup of the file named tomcat-users.xml. Open tomcat-users.xml up in your favorite editor and remove everything. Then replace it with the following:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="manager"/>
<user username="tomcat" password="tomcat" roles="manager"/>
</tomcat-users>

The values in "username" and "password" can (and should) be set to something else that would not easily be guessed but for this and subsequent articles, I'll be keeping it simple. That's all you need to do to enable user-level access to the Tomcat Manager application. Once tomcat is restarted, you're ready to use the Tomcat Manager.

Update:  Tomcat 7 introduces new management roles.  Please see my post "The New Manager Roles in Tomcat 7 Are Wonderful" for an introduction.

Tomcat Manager Usage Examples

Since I'm working with a tomcat 6 implementation installed on my local machine, all URLs will be accessed over localhost. The default path to load the Tomcat Manager application is http://localhost:8080/manager/html. You will be prompted to enter the username and password that was stored in tomcat-users.xml.

The default application page will appear. Please refer to the screenshot below for an example:

TomcatManagerMain



Click the "Server Status" link from the table near the top and you will get a display of the status of each connector, jvm memory stats for tomcat, and information regarding thread status.  

TomcatManagerServerStatus


Click "Complete Server Status" at the top and you'll get a whole bunch of useful statistics on the server and applications installed in the server.

Click on the "List Applications" link at the top left in order to get back to the main screen.  Now we''ll stop and start some running applications.  Scroll down to the "/docs" application.  You'll see a few links to the right, "Start", which is presently disabled, "Stop", "Reload", amnd "Undeploy".

TomcatDocsApps


To demonstrate what happens when you click "Stop", go ahead and click the "Stop" link, then click on the docs application link.  You'll get a 404.  

TomcatDocsUndeployed


Go back to the Tomcat Manager, click "Start" and the docs application is started again. 

TomcatDocsDeployed


Scroll down to the bottom of the Tomcat Manager's main page and you have basic OS and JVM info.

TomcatManagerServerInfo


As you can see, the type of information you get and the way you can start, stop, or undeploy applications is very useful for us but we certainly don't want untrusted access to get into the Tomcat Manager.  The next section will deal with restricting access.

Securing Access to the Tomcat Manager

As I already mentioned, the first thing to do is come up with a stronger value for both 'username' and 'password' in tomcat-users.xml.  If running on a UNIX platform, change permisiion on tomcat-users.xml to 600.  This will allow access to the user tomcat is running as, (as well as root) but will disallow access to all other accounts that might be on that system.

If you front-end your tomcat app server with Apache, you should double-check that you do not have a JkMount /manager/* statement anywhere in your apache configuration files. 

You can also enable the RemoteAddr or RemoteHostName valves to restrict access to the Tomcat Manager application.  It's easiest to modify $CATALINA_HOME/conf/context.xml and add the following at the bottom of the file:

<Context path="/manager" privileged="true"
docBase="/usr/local/tomcat6/webapps/manager">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.0\.0\.1"/>
</Context>

This will disallow access to all hosts except 127.0.0.1 (localhost). If your site uses static IP addressing for administration workstations, this isn't too big a deal but if you are using DHCP addressing, you may need to modify context.xml every time you want to use the Tomcat Manager, which can something of a pain if you have a large number of systems. However, you don't need to restart tomcat for context.xml changes to be made, which is why it's better to add them into this file then it is to add them to server.xml. (I also am reluctant to modify any application specific web.xml files, which is another option). context.xml changes are dynamic, you just need to wait a few moments for tomcat to re-check the file for changes.

Other Articles in my Tomcat Management Series Include:

Tomcat Management: Use Groovy to Interact with Tomcat Manager

Tomcat Management: Using the JMXProxy

Tomcat Management: Use the JMXProxy to Change Configuration

Tomcat Management: Jmx4Perl Makes it Easier

Tomcat Management: The New Manager Roles in Tomcat 7 Are Wonderful