简体   繁体   中英

Receiving values every second from Linux utilities in a Java program

I want to receive in Java the output from a Linux command line program. I need to read the values line by line, because the utilities are reporting their values once per second and the Java program should not need to wait until the end of execution. It should receive the values every second. The following small program works fine in the case of the ping command, but not for the perf stat command.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {

Process p;
BufferedReader reader;

public Main(int number) throws IOException {
        if (number == 1) {
        // does NOT work, blocks on readLine()
        p = Runtime.getRuntime().exec("sudo perf stat -e cycles -I 1000 -p 9264"); // change PID to the one to be monitored 
        }
        else if (number == 2) {
        // WORKS!
        p = Runtime.getRuntime().exec("ping www.google.com");
        }
        else {
        System.out.println("Either 1 or 2...");
        System.exit(0);
        }
        reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
}
public void process() throws IOException {
       String res = "";
       res = reader.readLine();
       System.out.println(res);

}
public static void main (String[] args) throws IOException, InterruptedException {
        Main myMain = new Main(Integer.parseInt(args[0]));
        while (true) {
        myMain.process();
        Thread.sleep(1000);
        }
}
}

So when running java Main 2 it works correctly, but when invoking java Main 1 it will block on the reader.readLine() call.

What's the difference between the two commands? Also with the command 'ls -l' it works correctly and I receive the values line by line.

EDIT: The command itself works fine, when I run it directly from the command line. The -I option was introduced in newer kernel versions, it did not exist before (I am using kernel 3.11, Ubuntu).

When using 2>$1 to get also the stderr, it will indeed read a value every second, but it will always read null.

The problem seems to be that perf stat does not use stdout by default, but stderr. See the log-fd option .

So you can either redirect stderr to stdout in the command you use,

Or you capture the input Stream from stderr of the Process

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM