การเรียกใช้เมธอด JMX MBean จากเชลล์สคริปต์


99

มีไลบรารีใดบ้างที่อนุญาตให้ฉันเรียกเมธอด JMX MBean จากเชลล์สคริปต์ เราเปิดเผยคำสั่งการดำเนินการ / ผู้ดูแลระบบผ่าน JMX และเราสามารถให้ผู้ดูแลระบบของเราใช้ JConsole หรือ VisualVM ได้ แต่งานบางอย่างควรปล่อยให้เป็นระบบอัตโนมัติ ในระบบอัตโนมัตินั้นเราต้องการที่จะเรียกเมธอด JMX MBean บนเซิร์ฟเวอร์ที่กำลังรันอยู่โดยเฉพาะจากเชลล์สคริปต์

คำตอบ:


106

ยูทิลิตี้บรรทัดคำสั่งต่อไปนี้ JMX พร้อมใช้งาน:

  1. jmxterm - ดูเหมือนจะเป็นยูทิลิตี้ที่โดดเด่นที่สุด
  2. cmdline-jmxclient - ใช้ในโครงการ WebArchive ดูเหมือนกระดูกเปลือยมาก (และไม่มีการพัฒนาตั้งแต่ปี 2549 ดูเหมือนว่า)
  3. Groovy script และ JMX - มีฟังก์ชั่น JMX ที่ทรงพลังจริงๆ แต่ต้องการการตั้งค่าไลบรารีที่ยุ่งยากและอื่น ๆ
  4. ฟังก์ชันบรรทัดคำสั่ง JManage - (ข้อเสียคือต้องใช้เซิร์ฟเวอร์ JManage ที่รันอยู่เพื่อใช้คำสั่งพร็อกซีผ่าน)

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 ตัวอย่าง:

หากคุณมีไฟล์

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

ด้วยการดำเนินการที่เรียกว่า:

  • jmxForceRefresh ()

จากนั้นคุณสามารถเขียนสคริปต์ทุบตีง่ายๆ (สมมติว่าคุณดาวน์โหลดcmdline-jmxclient-0.10.3.jarและใส่ในไดเร็กทอรีเดียวกับสคริปต์ของคุณ):

#!/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 ดูเหมือนจะไม่ทำงานบน Java 7 bugs.launchpad.net/jmxterm/+bug/942693
artbristol

19

ฉันได้พัฒนา jmxfuse ซึ่งแสดง JMX Mbeans เป็นระบบไฟล์ Linux FUSE ที่มีฟังก์ชันการทำงานคล้ายกับ / proc fs อาศัยJolokiaเป็นสะพานเชื่อมไปยัง JMX คุณสมบัติและการดำเนินการถูกเปิดเผยสำหรับการอ่านและการเขียน

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

ตัวอย่างเช่นในการอ่านแอตทริบิวต์:

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

เพื่อเขียนแอตทริบิวต์:

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

เพื่อเรียกใช้การดำเนินการ:

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

12

ปลั๊กอิน Syabru Nagios JMXจะหมายถึงการใช้จาก Nagios แต่ไม่จำเป็นต้อง Nagios และมีความสะดวกมากสำหรับการใช้บรรทัดคำสั่ง:

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

นี่ยอดเยี่ยมและเร็วมาก ประมาณ 0.3 วินาทีในการคืนค่าเทียบกับ 3 วินาทีสำหรับ jmxterm
sivann

9

อาจเป็นเรื่องง่ายที่สุดที่จะเขียนสิ่งนี้ใน 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[]{});    
    }

}

สิ่งนี้จะรวบรวมเป็น. class เดียวและไม่ต้องการการอ้างอิงในเซิร์ฟเวอร์หรือบรรจุภัณฑ์ maven ที่ซับซ้อน

โทรด้วย

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

5

มีความเสี่ยงเล็กน้อย แต่คุณสามารถรันคำสั่ง curl POST ด้วยค่าจากแบบฟอร์มจากคอนโซล JMX URL และการพิสูจน์ตัวตน http (หากจำเป็น):

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

ระวัง: ดัชนีวิธีการอาจเปลี่ยนแปลงเมื่อมีการเปลี่ยนแปลงซอฟต์แวร์ และการใช้งานเว็บฟอร์มอาจเปลี่ยนแปลงได้

ข้างต้นอ้างอิงจากแหล่งที่มาของหน้าบริการ JMX สำหรับการดำเนินการที่คุณต้องการดำเนินการ:

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

ที่มาของแบบฟอร์ม:

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>

ฉันใช้วิธีนี้จาก Java โดยใช้ไฟล์ HttpURLConnectionและฉันสามารถยืนยันได้ว่ามันใช้งานได้ (btw. submit=Invokeไม่จำเป็น)
ทอม

เป็นไปได้ไหมที่จะอธิบายวิธีการทำงาน ผมหมายถึงโดยใช้ค่าเริ่มต้น JMX และมีฉันเห็นrmi httpหมายความว่าต้องกำหนดค่าเซิร์ฟเวอร์ให้รองรับคำขอ jmx httpหรือไม่?
Psychozoic

3

ลองดูที่JManage ก็สามารถที่จะดำเนินการวิธีการ MBean และได้รับ / ชุดแอตทริบิวต์จากบรรทัดคำสั่ง


ข้อเสียเพียงอย่างเดียวคือการใช้ยูทิลิตี้บรรทัดคำสั่งซึ่งต้องใช้ JManage เพื่อเรียกใช้คำสั่งพร็อกซีไปยังเซิร์ฟเวอร์ JMX ของคุณ ฉันต้องการใช้วิธีที่เบากว่าโดยตรงกับเซิร์ฟเวอร์ JMX
Dougnukem

3

คุณอาจต้องการดู jmx4perl ให้การเข้าถึงแบบไม่ใช้ java ไปยัง MBeans ของ Java EE Server ระยะไกล อย่างไรก็ตามจำเป็นต้องติดตั้ง servlet เอเจนต์ขนาดเล็กบนแพลตฟอร์มเป้าหมายซึ่งจะให้การเข้าถึง JMX ที่เงียบสงบผ่าน HTTP พร้อมกับเพย์โหลด JSON (เวอร์ชัน 0.50 จะเพิ่มโหมดไม่ใช้เอเจนต์โดยใช้พร็อกซี JSR-160)

ข้อดีคือเวลาเริ่มต้นที่รวดเร็วเมื่อเทียบกับการเปิดตัว java JVM ในเครื่องและใช้งานง่าย jmx4perl มาพร้อมกับโมดูล Perl ครบชุดซึ่งสามารถใช้ในสคริปต์ของคุณเองได้อย่างง่ายดาย:

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

คุณยังสามารถใช้นามแฝงสำหรับคอมโบ MBean / Attribute / Operation ทั่วไป (เช่นสำหรับ MXBeans ส่วนใหญ่) สำหรับคุณสมบัติเพิ่มเติม (Nagios-Plugin, XPath-like access to complex attribute types, ... ) โปรดดูเอกสารประกอบของ jmx4perl


1

คำตอบ @Dougnukem ช่วยฉันได้มาก ฉันใช้วิธี Groovy (ใช้ groovy 2.3.3)

ฉันได้ทำการเปลี่ยนแปลงบางอย่างเกี่ยวกับโค้ด Dougnukem สิ่งนี้จะใช้ได้กับ Java 7 และจะพิมพ์แอตทริบิวต์สองรายการเพื่อ stdout ทุกๆ 10 วินาที

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

                }
            }

คอมไพล์โค้ดนี้ลงใน jar โดยใช้ maven-compiler-plugin ดังนั้นคุณจะไม่ต้องใช้การติดตั้งที่ยุ่งยากเพียงอย่างเดียว groovy-all.jar ด้านล่างนี้คือคำจำกัดความของปลั๊กอินที่เกี่ยวข้องและการอ้างอิง

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

ห่อด้วยไม้ตีหรือเปลือกและจะพิมพ์ข้อมูลไปยัง stdout


0

ฉันไม่แน่ใจเกี่ยวกับสภาพแวดล้อมที่เหมือนทุบตี คุณอาจลองใช้โปรแกรม Wrapper แบบง่ายๆใน Java (พร้อมอาร์กิวเมนต์ของโปรแกรม) ที่เรียกใช้ MBeans ของคุณบนรีโมตเซิร์ฟเวอร์ จากนั้นคุณสามารถเรียกใช้ Wrapper เหล่านี้จากเชลล์สคริปต์

หากคุณสามารถใช้บางอย่างเช่น Python หรือ Perl คุณอาจสนใจJSR-262ซึ่งช่วยให้คุณสามารถแสดงการทำงานของ JMX ผ่านบริการบนเว็บ สิ่งนี้ถูกกำหนดให้รวมอยู่ใน Java 7 แต่คุณอาจสามารถใช้ตัวเลือกรีลีสของการนำไปใช้อ้างอิงได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.