Why is the InputStreamReader not reading the output of the process in real time?

I am trying to use ProcessBuilder

to run some external commands like ifstat

or vmstat

in Linux.

Such commands support custom sampling intervals. If I add a sampling interval to an external command, for example ifstat 20

, then the command is output like this:

coolcfan@coolcfan-PC:~$ ifstat 20
       eth0               wlan0               vmnet1              vmnet8      
 KB/s in  KB/s out   KB/s in  KB/s out   KB/s in  KB/s out   KB/s in  KB/s out

      

after 20 seconds

   41.29      1.06      0.36      0.00      0.00      0.00      0.00      0.00

      

after 20 seconds

   16.67      0.58      0.38      0.00      0.00      0.00      0.00      0.00

      

However , when I run the command using Java code, the first part of the output will be read after 20 seconds, for example:

Start running "ifstat 20"

      

after 20 seconds

       eth0               wlan0               vmnet1              vmnet8      
 KB/s in  KB/s out   KB/s in  KB/s out   KB/s in  KB/s out   KB/s in  KB/s out
   66.61      1.73      1.29      0.01      0.00      0.00      0.00      0.00

      

When I use NIO server to run the command and use SocketChannel to send the output to the client, the problem is even more serious ... (my client needs to wait another 20 seconds to get the server output after the server shows the first output which is 20 seconds after starting process)

And I noticed that the output delay length is related to the I interval set in the command.

So why is the ISR not reading the live output?

Simple code snippet to demonstrate my question:

public static void main(String[] args) {
    ProcessBuilder pb = new ProcessBuilder();

    pb.command("ifstat 20".trim().split(" "));

    Process p = null;

    System.out.println("Start running \"ifstat 20\"");

    try {
        p = pb.start();

        char[] buf = new char[512];

        InputStreamReader isr = new InputStreamReader(p.getInputStream());

        int count = -1;

        while ((count = isr.read(buf, 0, buf.length)) != -1) {
            System.out.print(new String(buf, 0, count));
        }
    }
    catch (IOException ioe) {
    }
}

      


Update:

As Peter points out, this is not a Java related issue. This is a pipeline delay .

But I still don’t understand why it vmstat 20 | cat

doesn’t have this delay, but ifstat 20 | cat

will delay to show the heads?

+3


source to share


1 answer


He does.



It is the result of a process that is being delayed. STDIO performs buffering, which varies depending on whether it is fat or not a terminal.

+2


source







All Articles