Calling Jmx Mbean Method from a Shell Script

Calling JMX MBean method from a shell script

The following command line JMX utilities are available:

  1. jmxterm - seems to be the most fully featured utility.
  2. cmdline-jmxclient - used in the WebArchive project seems very bare bones (and no development since 2006 it looks like)
  3. Groovy script and JMX - provides some really powerful JMX functionality but requires groovy and other library setup.
  4. JManage command line
    functionality - (downside is
    that it requires a running JManage
    server to proxy commands through)

Groovy JMX Example:

import java.lang.management.*
import javax.management.ObjectName
import javax.management.remote.JMXConnectorFactory as JmxFactory
import javax.management.remote.JMXServiceURL as JmxUrl

def serverUrl = 'service:jmx:rmi:///jndi/rmi://localhost:9003/jmxrmi'
String beanName = "com.webwars.gameplatform.data:type=udmdataloadsystem,id=0"
def server = JmxFactory.connect(new JmxUrl(serverUrl)).MBeanServerConnection
def dataSystem = new GroovyMBean(server, beanName)

println "Connected to:\n$dataSystem\n"

println "Executing jmxForceRefresh()"
dataSystem.jmxForceRefresh();

cmdline-jmxclient example:

If you have an

  • MBean: com.company.data:type=datasystem,id=0

With an Operation called:

  • jmxForceRefresh()

Then you can write a simple bash script (assuming you download cmdline-jmxclient-0.10.3.jar and put in the same directory as your script):

#!/bin/bash

cmdLineJMXJar=./cmdline-jmxclient-0.10.3.jar
user=yourUser
password=yourPassword
jmxHost=localhost
port=9003

#No User and password so pass '-'
echo "Available Operations for com.company.data:type=datasystem,id=0"
java -jar ${cmdLineJMXJar} ${user}:${password} ${jmxHost}:${port} com.company.data:type=datasystem,id=0

echo "Executing XML update..."
java -jar ${cmdLineJMXJar} - ${jmxHost}:${port} com.company.data:type=datasystem,id=0 jmxForceRefresh

Simple way to programmatically access JMX console

Take a look at this SO question:

  • Calling JMX MBean method from a shell script

Linux Shell Script for calling JBoss 5x JMX's MBeans

Jboss shipped with twiddle script, you can get the list of Mbeans from jmx-console and query/invoke it through twiddle, such as

$JBOSS_HOME/twiddle.sh -s 127.0.0.1 invoke "jboss.system:type=ServerInfo" listMemoryPools "True"  
$JBOSS_HOME/twiddle.sh -s 127.0.0.1 get "jboss.system:type=ServerInfo"

and you can also use nagios-jmx-plugin

java -jar check_jmx.jar -U service:jmx:rmi://127.0.0.1/jndi/rmi://127.0.0.1:1090/jmxconnector --username admin --password admin -O "jboss.system:type=ServerInfo" -A FreeMemory 

How to query running java application from command line?

Use JMX

Considering your requirements, the easiest solution is most likely to use JMX. It's exactly what it's made for, as it's the Java Management eXtensions API.

You can find a nicely detailed tutorial trail in the Java Tutorial. It's relatively simple. Your Java program will listen for connections from JMX clients, and allow you to query your own Management Beans (MBean).

Administrators would then be able to use a JMX compatible client (for instance jconsole) or a custom client. See here for a custom JMX client example.

Another good - though somewhat ancient now - tutorial is Getting Started with MBeans.


If what you want is to intercept the return value of a particular function, not to create your own extension points for monitoring and administration, then you're more likely to want to use a debugger.

Also, you may be interested in these SO questions:

  • How to have 2 JVMs talk to one another
  • Calling JMX MBean method from a shell script

How to pass parameters into JMX MBean function from command line

According to the cmdline-jmxclient documentation:
http://crawler.archive.org/cmdline-jmxclient/ you have to use comma-delimited parameters to pass to your operation.

So in your case if would be:

java -jar cmdline-jmxclient-0.10.3.jar admin:P@sSw0rd10.11.12.13:1111 com.sun.management:type=HotSpotDiagnostic dumpHeap test,true

Take note that there is an present bug in the cmdline jar file that doesn't take into account Java primitives(int, booelean, byte, etc.) and will throw a ClassNotFoundException because it can't find by the primitive name.

If you find yourself coming across this issue you can either apply the patch to the jar code that is documented here: https://webarchive.jira.com/browse/HER-1630. Or simply change the type field in the jmx endpoint code from it's primitive type to it's Wrapper object type (int -> Integer)

Differences in calling JMX MBean remotely or from servlet deployed in the same JVM

I suspect what is happening here is that your servlet thread has a context classloader that is different from that of the MBeans that you are invoking against. Consequently, if the MBean attributes, operation parameters or return values contain types that are not core JVM classes (or classes not shared from the same root classloader), you will get ClassCast, ClassNotFound and ClassDefNotFound Exceptions.

This procedure may work for you. What you need to do is temporarily change the context classloader of the servlet thread to the same classloader as the MBean was loaded from. Once the invocation is complete, you set it back again. Since you know the ObjectName of the target MBean, the MBeanServer will supply you the correct classloader.

Here's a basic example:

public void callMBean() throws MalformedObjectNameException, NullPointerException, InstanceNotFoundException {
final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
try {
ObjectName targetObjectName = new ObjectName(".....");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ClassLoader tmpClassLoader = server.getClassLoaderFor(targetObjectName);
Thread.currentThread().setContextClassLoader(tmpClassLoader);
// ==========================================
// Invoke operations here
// ==========================================
} finally {
Thread.currentThread().setContextClassLoader(currentClassLoader);
}
}

Can one MBean link to another?

My conclusion is that you can return an ObjectName but it will not be linked when you access your M[X]Bean from the sun jconsole application. Instead you will just be presented the string representation of the ObjectName.

However, if you implement your own JMX client you can use these returned ObjectName to look up the "linked to" M[X]Bean.



Related Topics



Leave a reply



Submit