Memanggil metode JMX MBean dari skrip shell


98

Apakah ada pustaka yang memungkinkan saya memanggil metode JMX MBean dari skrip shell. Kami mengekspos beberapa operasi / perintah admin melalui JMX, dan kami dapat meminta admin kami menggunakan JConsole, atau VisualVM, tetapi beberapa tugas lebih baik diserahkan ke otomatisasi. Dalam otomatisasi itu kami ingin dapat memanggil metode JMX MBean di server kami yang sedang berjalan, sebaiknya dari skrip shell.

Jawaban:


106

Utilitas JMX baris perintah berikut tersedia:

  1. jmxterm - tampaknya merupakan utilitas berfitur paling lengkap.
  2. cmdline-jmxclient - digunakan dalam proyek WebArchive tampaknya sangat sederhana (dan sepertinya tidak ada pengembangan sejak 2006)
  3. Skrip Groovy dan JMX - menyediakan beberapa fungsionalitas JMX yang sangat kuat tetapi membutuhkan penyiapan library yang groovy dan lainnya.
  4. Fungsionalitas baris perintah JManage - (downside adalah bahwa ia membutuhkan server JManage yang berjalan untuk menjalankan perintah proxy)

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

cmdline-jmxclient contoh:

Jika Anda memiliki file

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

Dengan Operasi yang disebut:

  • jmxForceRefresh ()

Kemudian Anda dapat menulis skrip bash sederhana (dengan asumsi Anda mengunduh cmdline-jmxclient-0.10.3.jar dan meletakkannya di direktori yang sama dengan skrip Anda):

#!/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 tampaknya tidak bekerja pada Java 7 bugs.launchpad.net/jmxterm/+bug/942693
artbristol

19

Saya telah mengembangkan jmxfuse yang mengekspos JMX Mbeans sebagai sistem file FUSE Linux dengan fungsi yang mirip dengan / proc fs. Ini bergantung pada Jolokia sebagai jembatan ke JMX. Atribut dan operasi diekspos untuk membaca dan menulis.

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

Misalnya, untuk membaca atribut:

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

untuk menulis atribut:

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

untuk menjalankan operasi:

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

12

The Syabru nagios JMX Plugin dimaksudkan untuk digunakan dari nagios, tetapi tidak memerlukan nagios dan sangat nyaman untuk digunakan baris perintah:

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

Ini bagus, dan sangat cepat. Sekitar 0,3 detik untuk mengembalikan nilai vs 3 detik untuk jmxterm
sivann

9

Kemungkinan paling mudah untuk menulis ini di 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[]{})


    }

}

Ini akan dikompilasi menjadi satu .class dan tidak memerlukan ketergantungan di server atau pengemasan maven yang rumit.

sebut saja dengan

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

4

Sedikit berisiko, tetapi Anda dapat menjalankan perintah POST curl dengan nilai dari formulir dari konsol JMX, otentikasi URL dan http-nya (jika diperlukan):

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

Hati-hati: indeks metode dapat berubah dengan perubahan pada perangkat lunak. Dan implementasi formulir web bisa berubah.

Di atas didasarkan pada sumber halaman layanan JMX untuk operasi yang ingin Anda lakukan:

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

Sumber formulir:

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>

Saya menerapkannya dengan cara ini dari Java menggunakan a HttpURLConnectiondan saya dapat mengonfirmasi bahwa itu berfungsi. (btw. submit=Invoketidak perlu)
tom

apakah mungkin untuk menjelaskan cara kerjanya? Maksud saya, secara default menggunakan jmx rmi, dan di sana saya melihat http. Apakah ini berarti bahwa server harus dikonfigurasi untuk mendukung permintaan jmx http?
Psikozoikum

3

Lihat JManage . Itu dapat mengeksekusi metode MBean dan mendapatkan / mengatur atribut dari baris perintah .


Satu-satunya downside adalah menggunakan utilitas baris perintah yang membutuhkan JManage untuk menjalankan perintah proxy ke server JMX Anda. Saya lebih suka pendekatan yang lebih ringan langsung ke server JMX itu sendiri.
Dougnukem

3

Anda mungkin juga ingin melihat jmx4perl . Ini menyediakan akses tanpa java ke MBeans Server EE Java jarak jauh. Namun, servlet agen kecil perlu diinstal pada platform target, yang menyediakan Akses JMX yang tenang melalui HTTP dengan payload JSON. (Versi 0.50 akan menambahkan mode tanpa agen dengan menerapkan proxy JSR-160).

Keuntungannya adalah waktu startup yang cepat dibandingkan dengan meluncurkan Java JVM lokal dan kemudahan penggunaan. jmx4perl hadir dengan satu set lengkap modul Perl yang dapat dengan mudah digunakan di skrip Anda sendiri:

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

Anda juga dapat menggunakan alias untuk combo MBean / Atribut / Operasi umum (misalnya untuk kebanyakan MXBeans). Untuk fitur tambahan (Nagios-Plugin, akses mirip XPath ke tipe atribut kompleks, ...), silakan merujuk ke dokumentasi jmx4perl.


1

Jawaban @Dougnin sangat membantu saya. Saya telah mengambil pendekatan Groovy (menggunakan groovy 2.3.3).

Saya melakukan beberapa perubahan pada kode Dougnukem. Ini akan bekerja dengan Java 7 dan akan mencetak dua atribut ke stdout setiap 10 detik.

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

                }
            }

Kompilasi kode ini ke dalam jar menggunakan maven-compiler-plugin sehingga Anda tidak perlu menginstal groovy hanya pada groovy-all.jar. Di bawah ini adalah definisi dan ketergantungan plugin yang relevan.

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

Bungkus dengan bat atau shell dan itu akan mencetak data ke stdout.


0

Saya tidak yakin tentang lingkungan seperti pesta. Anda dapat mencoba beberapa program pembungkus sederhana di Java (dengan argumen program) yang menjalankan MBeans Anda di server jarak jauh. Anda kemudian dapat memanggil pembungkus ini dari skrip shell

Jika Anda dapat menggunakan sesuatu seperti Python atau Perl, Anda mungkin tertarik dengan JSR-262 yang memungkinkan Anda mengekspos operasi JMX melalui layanan web. Ini dijadwalkan untuk disertakan dalam Java 7, tetapi Anda mungkin dapat menggunakan kandidat rilis dari implementasi referensi

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.