Aufrufen der JMX-MBean-Methode aus einem Shell-Skript


98

Gibt es Bibliotheken, mit denen ich eine JMX-MBean-Methode aus einem Shell-Skript aufrufen kann? Wir stellen einige Operations / Admin-Befehle über JMX zur Verfügung, und unsere Administratoren könnten JConsole oder VisualVM verwenden, aber einige Aufgaben sollten besser der Automatisierung überlassen werden. In dieser Automatisierung möchten wir eine JMX-MBean-Methode auf unserem laufenden Server aufrufen können, vorzugsweise über ein Shell-Skript.

Antworten:


106

Die folgenden JMX-Dienstprogramme für die Befehlszeile sind verfügbar:

  1. jmxterm - scheint das Dienstprogramm mit den meisten Funktionen zu sein.
  2. cmdline-jmxclient - verwendet im WebArchive-Projekt scheint sehr nackt zu sein (und keine Entwicklung seit 2006, wie es aussieht)
  3. Groovy-Skript und JMX - bietet einige wirklich leistungsstarke JMX-Funktionen, erfordert jedoch Groovy- und andere Bibliothekseinstellungen.
  4. JManage-Befehlszeilenfunktionalität - (Nachteil ist, dass ein laufender JManage-Server erforderlich ist, um Befehle durchzuleiten)

Groovy JMX Beispiel:

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 Beispiel:

Wenn Sie eine haben

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

Mit einer Operation namens:

  • jmxForceRefresh ()

Dann können Sie ein einfaches Bash-Skript schreiben (vorausgesetzt, Sie laden cmdline-jmxclient-0.10.3.jar herunter und legen es im selben Verzeichnis wie Ihr Skript ab):

#!/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

jmxterm scheint nicht auf Java 7 bugs.launchpad.net/jmxterm/+bug/942693
artbristol

19

Ich habe jmxfuse entwickelt, das JMX Mbeans als Linux FUSE-Dateisystem mit ähnlichen Funktionen wie / proc fs verfügbar macht. Es basiert auf Jolokia als Brücke zu JMX. Attribute und Operationen werden zum Lesen und Schreiben angezeigt.

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

So lesen Sie beispielsweise ein Attribut:

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

ein Attribut schreiben:

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

So rufen Sie eine Operation auf:

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

12

Das Syabru Nagios JMX-Plugin soll von Nagios verwendet werden, benötigt jedoch kein Nagios und ist sehr praktisch für die Befehlszeilenverwendung:

~$ ./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;;;;

Das ist großartig und sehr schnell. Etwa 0,3 Sekunden, um einen Wert gegen 3 Sekunden für jmxterm
sivann

9

Möglicherweise ist es am einfachsten, dies in Java zu schreiben

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[]{})


    }

}

Dies würde zu einer einzelnen Klasse kompiliert und erfordert keine Abhängigkeiten im Server oder komplizierte Maven-Pakete.

nenne es mit

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

4

Ein wenig riskant, aber Sie könnten einen Curl-POST-Befehl mit den Werten aus dem Formular der JMX-Konsole, der URL und der http-Authentifizierung ausführen (falls erforderlich):

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

Achtung: Der Methodenindex kann sich bei Änderungen an der Software ändern. Und die Implementierung des Webformulars könnte sich ändern.

Das Obige basiert auf der Quelle der JMX-Service-Seite für den Vorgang, den Sie ausführen möchten:

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

Quelle des Formulars:

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>

Ich habe es auf diese Weise aus Java mit a implementiert HttpURLConnectionund kann bestätigen, dass es funktioniert. (Übrigens submit=Invokeist unnötig)
Tom

Kann man beschreiben, wie es funktioniert? Ich meine, standardmäßig verwendet jmx rmi, und dort sehe ich http. Bedeutet dies, dass der Server so konfiguriert werden muss, dass JMX-Anforderungen unterstützt werden http?
Psychozoikum

3

Schauen Sie sich JManage an . Es ist in der Lage, MBean-Methoden auszuführen und Attribute über die Befehlszeile abzurufen / festzulegen .


Der einzige Nachteil ist die Verwendung des Befehlszeilenprogramms, für das JManage ausgeführt werden muss, um Proxy-Befehle an Ihre JMX-Server zu senden. Ich möchte lieber einen leichteren Ansatz direkt zum JMX-Server selbst.
Dougnukem

3

Vielleicht möchten Sie auch einen Blick auf jmx4perl werfen . Es bietet Java-freien Zugriff auf die MBeans eines Remote-Java EE-Servers. Auf der Zielplattform muss jedoch ein kleines Agentenservlet installiert werden, das einen erholsamen JMX-Zugriff über HTTP mit einer JSON-Nutzlast bietet. (Version 0.50 fügt einen agentenlosen Modus hinzu, indem ein JSR-160-Proxy implementiert wird.)

Vorteile sind schnelle Startzeiten im Vergleich zum Starten einer lokalen Java-JVM und einfache Bedienung. jmx4perl enthält einen vollständigen Satz von Perl-Modulen, die problemlos in Ihren eigenen Skripten verwendet werden können:

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);

Sie können auch Alias ​​für gängige MBean- / Attribut- / Operationskombinationen verwenden (z. B. für die meisten MXBeans). Weitere Funktionen (Nagios-Plugin, XPath-ähnlicher Zugriff auf komplexe Attributtypen, ...) finden Sie in der Dokumentation von jmx4perl.


1

@ Dougnukem Antwort hat mir sehr geholfen. Ich habe den Groovy-Ansatz gewählt (mit Groovy 2.3.3).

Ich habe einige Änderungen am Dougnukem-Code vorgenommen. Dies funktioniert mit Java 7 und druckt alle 10 Sekunden zwei Attribute auf stdout.

        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)
                    }

                }
            }

Kompilieren Sie diesen Code mit dem maven-compiler-plugin in ein jar, damit Sie nicht nur die groovy-all.jar-Installation benötigen. Unten finden Sie die relevante Definition und Abhängigkeit des Plugins.

   <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>

Wickeln Sie es mit einem Schläger oder einer Muschel ein und es druckt die Daten auf stdout.


0

Ich bin mir nicht sicher über die Bash-ähnliche Umgebung. Sie können einige einfache Wrapper-Programme in Java (mit Programmargumenten) ausprobieren, die Ihre MBeans auf dem Remote-Server aufrufen. Sie können diese Wrapper dann über das Shell-Skript aufrufen

Wenn Sie etwas wie Python oder Perl verwenden können, sind Sie möglicherweise an JSR-262 interessiert , mit dem Sie JMX-Vorgänge über Webdienste verfügbar machen können. Dies soll in Java 7 enthalten sein, Sie können jedoch möglicherweise einen Release Candidate der Referenzimplementierung verwenden

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.