Calling JMX MBean method from a shell script

偶尔善良 提交于 2019-11-26 06:13:45

问题


Are there any libraries that would allow me to call a JMX MBean method from a shell script. We expose some operations/admin commands through JMX, and we could have our admins use JConsole, or VisualVM, but some tasks are better left to automation. In that automation we\'d like to be able to call a JMX MBean method on our running server, preferably from a shell script.


回答1:


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



回答2:


I've developed jmxfuse which exposes JMX Mbeans as a Linux FUSE filesystem with similar functionality as the /proc fs. It relies on Jolokia as the bridge to JMX. Attributes and operations are exposed for reading and writing.

http://code.google.com/p/jmxfuse/

For example, to read an attribute:

me@oddjob:jmx$ cd log4j/root/attributes
me@oddjob:jmx$ cat priority

to write an attribute:

me@oddjob:jmx$ echo "WARN" > priority

to invoke an operation:

me@oddjob:jmx$ cd Catalina/none/none/WebModule/localhost/helloworld/operations/addParameter
me@oddjob:jmx$ echo "myParam myValue" > invoke



回答3:


The Syabru Nagios JMX plugin is meant to be used from Nagios, but doesn't require Nagios and is very convenient for command-line use:

~$ ./check_jmx -U service:jmx:rmi:///jndi/rmi://localhost:1099/JMXConnector --username myuser --password mypass -O java.lang:type=Memory -A HeapMemoryUsage -K used 
JMX OK - HeapMemoryUsage.used = 445012360 | 'HeapMemoryUsage used'=445012360;;;;



回答4:


Potentially its easiest to write this in Java

import javax.management.*;
import javax.management.remote.*;

public class JmxInvoke {

    public static void main(String... args) throws Exception {

        JMXConnectorFactory.connect(new JMXServiceURL(args[0]))
            .getMBeanServerConnection().invoke(new ObjectName(args[1]), args[2], new Object[]{}, new String[]{})


    }

}

This would compile to a single .class and needs no dependencies in server or any complicated maven packaging.

call it with

javac JmxInvoke.java
java -cp . JmxInvoke [url] [beanName] [method]



回答5:


A little risky, but you could run a curl POST command with the values from the form from the JMX console, its URL and http authentication (if required):

curl -s -X POST --user 'myuser:mypass'
  --data "action=invokeOp&name=App:service=ThisServiceOp&methodIndex=3&arg0=value1&arg1=value1&submit=Invoke"
  http://yourhost.domain.com/jmx-console/HtmlAdaptor

Beware: the method index may change with changes to the software. And the implementation of the web form could change.

The above is based on source of the JMX service page for the operation you want to perform:

http://yourhost.domain.com/jmx-console/HtmlAdaptor?action=inspectMBean&name=YourJMXServiceName

Source of the form:

form method="post" action="HtmlAdaptor">
   <input type="hidden" name="action" value="invokeOp">
   <input type="hidden" name="name" value="App:service=ThisServiceOp">
   <input type="hidden" name="methodIndex" value="3">
   <hr align='left' width='80'>
   <h4>void ThisOperation()</h4>
   <p>Operation exposed for management</p>
    <table cellspacing="2" cellpadding="2" border="1">
        <tr class="OperationHeader">
            <th>Param</th>
            <th>ParamType</th>
            <th>ParamValue</th>
            <th>ParamDescription</th>
        </tr>
        <tr>
            <td>p1</td>
           <td>java.lang.String</td>
         <td> 
            <input type="text" name="arg0">
         </td>
         <td>(no description)</td>
        </tr>
        <tr>
            <td>p2</td>
           <td>arg1Type</td>
         <td> 
            <input type="text" name="arg1">
         </td>
         <td>(no description)</td>
        </tr>
    </table>
    <input type="submit" value="Invoke">
</form>



回答6:


Take a look at JManage. It's able to execute MBean methods and get / set attributes from command line.




回答7:


You might want also to have a look at jmx4perl. It provides java-less access to a remote Java EE Server's MBeans. However, a small agent servlet needs to be installed on the target platform, which provides a restful JMX Access via HTTP with a JSON payload. (Version 0.50 will add an agentless mode by implementing a JSR-160 proxy).

Advantages are quick startup times compared to launching a local java JVM and ease of use. jmx4perl comes with a full set of Perl modules which can be easily used in your own scripts:

use JMX::Jmx4Perl;
use JMX::Jmx4Perl::Alias;   # Import certains aliases for MBeans

print "Memory Used: ",
      JMX::Jmx4Perl
          ->new(url => "http://localhost:8080/j4p")
          ->get_attribute(MEMORY_HEAP_USED);

You can also use alias for common MBean/Attribute/Operation combos (e.g. for most MXBeans). For additional features (Nagios-Plugin, XPath-like access to complex attribute types, ...), please refer to the documentation of jmx4perl.




回答8:


@Dougnukem answer helped me a lot. I have taken the Groovy approach (using groovy 2.3.3).

I did some changes on Dougnukem code. This will work with Java 7 and will print two attributes to stdout every 10 sec.

        package com.my.company.jmx
        import groovy.util.GroovyMBean;
        import javax.management.remote.JMXServiceURL
        import javax.management.remote.JMXConnectorFactory
        import java.lang.management.*

            class Monitor {
                static main(args) {
                    def serverUrl = 'service:jmx:rmi:///jndi/rmi://localhost:5019/jmxrmi'
                    String beanName = "Catalina:type=DataSource,class=javax.sql.DataSource,name=\"jdbc/CommonDB\""
                    println  "numIdle,numActive"

                    while(1){
                        def server = JMXConnectorFactory.connect(new JMXServiceURL(serverUrl))
                       //make sure to reconnect in case the jvm was restrated 
                        server.connect()
                        GroovyMBean mbean = new GroovyMBean(server.MBeanServerConnection, beanName)
                        println  "${mbean.numIdle},${mbean.numActive}"
                        server.close()
                        sleep(10000)
                    }

                }
            }

Compile this code into a jar using maven-compiler-plugin so you will not require groovy installation only the groovy-all.jar . Below is the relevant plugin definition and dependency.

   <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <compilerId>groovy-eclipse-compiler</compilerId>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-eclipse-compiler</artifactId>
                        <version>2.8.0-01</version>
                    </dependency>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-eclipse-batch</artifactId>
                        <version>2.3.4-01</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.4.3</version>
        </dependency>
    </dependencies>

Wrap it with a bat or a shell and it will print the data to stdout.




回答9:


I'm not sure about bash-like environment. You might try some simple wrapper programs in Java (with program arguments) that invoke your MBeans on the remote server. You can then call these wrappers from the shell script

If you can use something like Python or Perl, you might be interested in JSR-262 which allows you to expose JMX operations over web services. This is scheduled to be included in Java 7 but you might be able to use a release candidate of the reference implementation



来源:https://stackoverflow.com/questions/1751130/calling-jmx-mbean-method-from-a-shell-script

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!