web-dev-qa-db-fra.com

Appel de la méthode JMX MBean à partir d'un script Shell

Existe-t-il des bibliothèques qui me permettraient d’appeler une méthode JMX MBean à partir d’un script Shell? Nous exposons certaines commandes opérations/admin via JMX et nos administrateurs peuvent utiliser JConsole ou VisualVM, mais il est préférable de laisser certaines tâches à l’automatisation. Dans cette automatisation, nous aimerions pouvoir appeler une méthode JMX MBean sur notre serveur en cours d'exécution, de préférence à partir d'un script Shell.

92
Dougnukem

Les utilitaires JMX en ligne de commande suivants sont disponibles:

  1. jmxterm - semble être l'utilitaire le plus complet.
  2. cmdline-jmxclient - utilisé dans le projet WebArchive semble très simple (et aucun développement depuis 2006, ça ressemble à)
  3. script Groovy et JMX - fournit des fonctionnalités JMX très puissantes, mais nécessite l'installation de bibliothèques groovy et autres.
  4. fonctionnalité de ligne de commande JManagel'inconvénient est qu'un serveur JManage en cours d'exécution est nécessaire pour exécuter les commandes proxy)

Exemple de Groovy JMX:

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

Exemple avec cmdline-jmxclient:

Si vous avez un

Avec une opération appelée:

Ensuite, vous pouvez écrire un script bash simple (en supposant que vous téléchargiez --- (cmdline-jmxclient-0.10.3.jar et placez-le dans le même répertoire que votre 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
99
Dougnukem

J'ai développé jmxfuse qui expose JMX Mbeans en tant que système de fichiers Linux Fuse avec des fonctionnalités similaires à celles du fichier/proc. Il s'appuie sur Jolokia comme pont vers JMX. Les attributs et les opérations sont exposés en lecture et en écriture.

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

Par exemple, pour lire un attribut:

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

écrire un attribut:

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

invoquer une opération:

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

Le plugin Syabru Nagios JMX est destiné à être utilisé depuis Nagios, mais ne nécessite pas Nagios et est très pratique pour une utilisation en ligne de commande:

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

C'est potentiellement le plus facile à écrire en 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[]{})


    }

}

Cela compilerait dans une seule classe .class et ne nécessiterait aucune dépendance du serveur ni aucun empaquetage maven compliqué.

appelle avec

javac JmsInvoke.Java
java -cp . JmxInvoke [url] [beanName] [method]
7
teknopaul

Un peu risqué, mais vous pourriez exécuter une commande curl POST) avec les valeurs du formulaire de la console JMX, son authentification URL et http (si nécessaire):

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

Attention: l'index de méthode peut changer avec les modifications du logiciel. Et la mise en œuvre du formulaire Web pourrait changer.

Ce qui précède est basé sur le source de la page de service JMX pour l’opération que vous souhaitez effectuer:

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

Source de la forme:

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

Vous voudrez peut-être aussi jeter un oeil à jmx4Perl . Il fournit un accès sans Java à un MBean distant Java EE Server. Cependant, un petit servlet d'agent doit être installé sur la plate-forme cible, ce qui permet un accès reposant à JMX via HTTP avec une charge JSON . (La version 0.50 ajoutera un mode sans agent en implémentant un proxy JSR-160).

Les avantages sont des temps de démarrage rapides comparés au lancement d'une JVM locale Java et facilité d'utilisation). Jmx4Perl est livré avec un ensemble complet de modules Perl qui peuvent facilement être utilisés dans vos propres 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);

Vous pouvez également utiliser un alias pour les combos MBean/Attribut/Opération courants (par exemple, pour la plupart des MXBeans). Pour des fonctionnalités supplémentaires (Nagios-Plugin, accès XPath à des types d'attributs complexes, ...), veuillez vous reporter à la documentation de jmx4Perl.

3
Roland Huß

Jetez un oeil à JManage . Il est capable d'exécuter des méthodes MBean et d'obtenir/définir des attributs à partir de ligne de commande .

3
ChssPly76

@Dougnukem answer m'a beaucoup aidé. J'ai adopté l'approche Groovy (en utilisant groovy 2.3.3).

J'ai fait quelques changements sur le code Dougnukem. Cela fonctionnera avec Java 7 et imprimera deux attributs sur la sortie standard toutes les 10 secondes.

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

                }
            }

Compilez ce code dans un fichier jar à l'aide de maven-compiler-plugin afin de ne pas nécessiter une installation groovy uniquement du fichier groovy-all.jar. Vous trouverez ci-dessous la définition et la dépendance du plugin.

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

Enveloppez-le avec une batte ou un shell et il imprimera les données sur la sortie standard.

1
Haim Raman

Je ne suis pas sûr de l'environnement bash-like. Vous pouvez essayer quelques programmes d'encapsulation simples dans Java (avec les arguments du programme) qui appellent vos MBeans sur le serveur distant. Vous pouvez ensuite appeler ces wrappers à partir du script Shell.

Si vous pouvez utiliser quelque chose comme Python ou Perl, cela pourrait vous intéresser JSR-262 , ce qui vous permet d'exposer les opérations JMX sur des services Web. inclus dans Java 7 mais vous pourrez peut-être utiliser une version candidate de implémentation de référence

0
Kevin