• Home

  • Custom Ecommerce
  • Application Development
  • Database Consulting
  • Cloud Hosting
  • Systems Integration
  • Legacy Business Systems
  • Security & Compliance
  • GIS

  • Expertise

  • About Us
  • Our Team
  • Clients
  • Blog
  • Careers

  • VisionPort

  • Contact
  • Our Blog

    Ongoing observations by End Point Dev people

    Getting Output from jps with NRPE

    A mellow river winds across the image, with verdant trees reaching over the water.

    One of the tools our hosting team uses for server and site monitoring is Icinga (which is based on Nagios). When monitoring host resources, one of the tools we use is Nagios Remote Plugin Executor or NRPE.

    We encountered an issue when executing NRPE: though NRPE runs on the server being monitored, it wasn’t giving the same output as a script which was executed on the server itself. The NRPE-related call should have no issues be executed on the target server, as it is declared in the sudoers file (commonly /etc/sudoers). In this post, I will explain how to get the output from jps (Java Virtual Machine Process Status Tool), which can only be executed as root.

    Getting process information with jps

    Let’s say we have a “hello world” program named Hello.java. How do we get the process’s state from Icinga’s head server?

    First, let’s compile and run the program.

    public class Hello {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
    
            try {
                Thread.sleep(3000);  // Sleep for 3 seconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    java Hello.java
    Hello, World!
    

    The program will run until it times out.

    First, let’s check the process by running ps on the server:

    # ps aux | grep Hello.java | grep -v grep
    najmi      61609 16.7  0.3 11541184 109360 pts/5 Sl+  01:19   0:00 java Hello.java
    

    We can also get the process ID with jps. Here’s the output from the “najmi” user view:

    # sudo -s -u najmi jps -l
    61609 jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher
    61695 jdk.jcmd/sun.tools.jps.Jps
    

    And from the “root” user view:

    # whoami
    root
    # jps -l
    61609 jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher
    61852 jdk.jcmd/sun.tools.jps.Jps
    # ps aux | grep Hello.java | grep -v grep
    najmi      61609  1.2  0.3 11541184 109360 pts/5 Sl+  01:19   0:01 java Hello.java
    

    However, the “nrpe” user does not see it:

    # sudo -s -u nrpe jps -l
    61790 jdk.jcmd/sun.tools.jps.Jps
    

    Instead of running the jps command directly as Nagios, we will let the system run jps as root and dump the results into a file. An NRPE-based script will later read the output and feed the result to the dashboard.

    Running jps as root, with output to a file

    For this example, I started the jetty process with sudo.

    sudo /usr/share/jetty/bin/jetty.sh start
    

    Now let’s check whether the “jetty” service is running or not.

    First we’ll check the status as a non-root user. It sees the process as “not running”.

    $ /usr/share/jetty/bin/jetty.sh status
    ** WARNING: JETTY_LOGS is Deprecated. Please configure logging within the jetty base.
    Jetty NOT running
    
    JAVA                  =  /usr/bin/java
    JAVA_OPTIONS          =
    JETTY_HOME            =  /usr/share/jetty
    JETTY_BASE            =  /usr/share/jetty
    START_D               =  /usr/share/jetty/start.d
    START_INI             =  /usr/share/jetty/start.ini
    JETTY_START           =  /usr/share/jetty/start.jar
    JETTY_CONF            =  /usr/share/jetty/etc/jetty.conf
    JETTY_ARGS            =  jetty.state=/run/jetty/jetty.state jetty.pid=/run/jetty/jetty.pid --module=pid,state
    JETTY_RUN             =  /run/jetty
    JETTY_PID             =  /run/jetty/jetty.pid
    JETTY_START_LOG       =  /run/jetty/jetty-start.log
    JETTY_STATE           =  /run/jetty/jetty.state
    JETTY_START_TIMEOUT   =  60
    JETTY_SYS_PROPS       =
    RUN_ARGS              =  -Djava.io.tmpdir=/tmp -Djetty.home=/usr/share/jetty -Djetty.base=/usr/share/jetty --class-path /etc/jetty/resources:/usr/share/jetty/lib/logging/slf4j-api-2.0.16.jar:/usr/share/jetty/lib/logging/jetty-slf4j-impl-12.0.16.jar:/usr/share/jetty/lib/jetty-http-12.0.16.jar:/usr/share/jetty/lib/jetty-server-12.0.16.jar:/usr/share/jetty/lib/jetty-xml-12.0.16.jar:/usr/share/jetty/lib/jetty-util-12.0.16.jar:/usr/share/jetty/lib/jetty-io-12.0.16.jar org.eclipse.jetty.xml.XmlConfiguration java.version=23.0.1 jetty.base=/usr/share/jetty jetty.base.uri=file:///usr/share/jetty jetty.home=/usr/share/jetty jetty.home.uri=file:///usr/share/jetty jetty.pid=/run/jetty/jetty.pid jetty.state=/run/jetty/jetty.state jetty.webapp.addHiddenClasses=org.eclipse.jetty.logging.,file:///usr/share/jetty/lib/logging/,org.slf4j. runtime.feature.alpn=true slf4j.version=2.0.16 /etc/jetty/jetty-bytebufferpool.xml /etc/jetty/jetty-pid.xml /etc/jetty/jetty-threadpool.xml /etc/jetty/jetty.xml /etc/jetty/jetty-state.xml
    ID                    =  uid=1000(user) gid=1000(user) groups=1000(user),90(network),98(power),984(users),987(storage),991(lp),994(input),996(audio),998(wheel)
    JETTY_USER            =  jetty
    USE_START_STOP_DAEMON =  0
    START_STOP_DAEMON     =  0
    

    Now, let’s check the status of the jetty service with sudo:

    $ sudo /usr/share/jetty/bin/jetty.sh status
    ** WARNING: JETTY_LOGS is Deprecated. Please configure logging within the jetty base.
    Jetty running pid=89969
    
    JAVA                  =  /usr/bin/java
    JAVA_OPTIONS          =
    JETTY_HOME            =  /usr/share/jetty
    JETTY_BASE            =  /usr/share/jetty
    START_D               =  /usr/share/jetty/start.d
    START_INI             =  /usr/share/jetty/start.ini
    JETTY_START           =  /usr/share/jetty/start.jar
    JETTY_CONF            =  /usr/share/jetty/etc/jetty.conf
    JETTY_ARGS            =  jetty.state=/run/jetty/jetty.state jetty.pid=/run/jetty/jetty.pid --module=pid,state
    JETTY_RUN             =  /run/jetty
    JETTY_PID             =  /run/jetty/jetty.pid
    JETTY_START_LOG       =  /run/jetty/jetty-start.log
    JETTY_STATE           =  /run/jetty/jetty.state
    JETTY_START_TIMEOUT   =  60
    JETTY_SYS_PROPS       =
    RUN_ARGS              =  -Djava.io.tmpdir=/tmp -Djetty.home=/usr/share/jetty -Djetty.base=/usr/share/jetty --class-path /etc/jetty/resources:/usr/share/jetty/lib/logging/slf4j-api-2.0.16.jar:/usr/share/jetty/lib/logging/jetty-slf4j-impl-12.0.16.jar:/usr/share/jetty/lib/jetty-http-12.0.16.jar:/usr/share/jetty/lib/jetty-server-12.0.16.jar:/usr/share/jetty/lib/jetty-xml-12.0.16.jar:/usr/share/jetty/lib/jetty-util-12.0.16.jar:/usr/share/jetty/lib/jetty-io-12.0.16.jar org.eclipse.jetty.xml.XmlConfiguration java.version=23.0.1 jetty.base=/usr/share/jetty jetty.base.uri=file:///usr/share/jetty jetty.home=/usr/share/jetty jetty.home.uri=file:///usr/share/jetty jetty.pid=/run/jetty/jetty.pid jetty.state=/run/jetty/jetty.state jetty.webapp.addHiddenClasses=org.eclipse.jetty.logging.,file:///usr/share/jetty/lib/logging/,org.slf4j. runtime.feature.alpn=true slf4j.version=2.0.16 /etc/jetty/jetty-bytebufferpool.xml /etc/jetty/jetty-pid.xml /etc/jetty/jetty-threadpool.xml /etc/jetty/jetty.xml /etc/jetty/jetty-state.xml
    ID                    =  uid=0(root) gid=0(root) groups=0(root)
    JETTY_USER            =  jetty
    USE_START_STOP_DAEMON =  0
    START_STOP_DAEMON     =  0
    

    Then, check that it’s running with jps as root, and note that the nrpe user still can’t see the process using jps:

    $ sudo /usr/share/jetty/bin/jetty.sh status 2>/dev/null | grep "running pid"
    Jetty running pid=89969
    
    $ sudo jps -l
    89969 org.eclipse.jetty.xml.XmlConfiguration
    91635 jdk.jcmd/sun.tools.jps.Jps
    
    $ sudo -s -u nrpe jps -l
    91711 jdk.jcmd/sun.tools.jps.Jps
    

    We can decide whether to use the “jetty” service script as the process check tool, or whether to use jps. For this post, we’ll focus on jps.

    We can run jps as root in a Bash script to dump the Java process ID into a temporary file. We can then use this script as an NRPE script.

    #!/bin/bash
    
    # Check if program name was provided
    if [ -z "$1" ]; then
        echo "UNKNOWN: Please specify a program name to check"
        exit 3
    fi
    
    TEMP_FILE="/tmp/java_pid.txt"
    
    # Clear the temp file first
    > $TEMP_FILE
    
    # Run jps and save output to temp file
    jps -l > $TEMP_FILE
    
    # Check if program is in the temp file
    if grep -q "$1" $TEMP_FILE; then
        PID=$(grep "$1" $TEMP_FILE | awk '{print $1}')
        echo "OK - $1 is running with PID $PID"
        exit 0
    else
        echo "CRITICAL - $1 is down"
        exit 2
    fi
    

    Conclusion

    Most of time, using ps or pgrep will be adequate to check for running processes. This post just shows how to get the output from jps, when you need to use jps. As for checking the status of the jetty service, /usr/share/jetty/bin/jetty.sh status might be fine as well, but the process of filtering, parsing, and feeding the output to the NRPE plugin should be pretty much the same.

    There could be another way to solve this issue, which I am not be aware of. The method I shared above is just one way to get jps’s report working with NRPE. Please let me know if you have experience with jps and Icinga/​Nagios, and how you handle their reporting.

    linux monitoring nagios java


    Comments