3

我正在尝试使用ProcessBuilder来运行一些外部命令,例如Linuxifstatvmstat在 Linux 中。

此类命令支持自定义采样间隔。如果我在外部命令中添加一个采样间隔,例如 ,ifstat 20那么该命令将输出如下:

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

20秒后

   41.29      1.06      0.36      0.00      0.00      0.00      0.00      0.00

再过20秒

   16.67      0.58      0.38      0.00      0.00      0.00      0.00      0.00

但是,当我使用我的 Java 代码运行命令时,将在 20 秒后读取输出的第一部分,如下所示:

Start running "ifstat 20"

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
   66.61      1.73      1.29      0.01      0.00      0.00      0.00      0.00

当我使用 NIO 服务器运行命令并使用 SocketChannel 将输出发送到客户端时,问题更加严重......(我的客户端需要再等待 20 秒才能在服务器显示第一个后从服务器获取输出进程开始后 20 秒的输出)

而且我注意到输出延迟的长度与我为命令设置的间隔有关。

那么为什么 ISR 不实时读取输出呢?

一个简单的测试代码片段来演示我的问题:

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

更新:

正如彼得的评论,这不是与 Java 相关的问题。这是管道延迟

但是我还是不明白,为什么vmstat 20 | cat没有这个延迟,而ifstat 20 | cat会延迟露头呢?

4

1 回答 1

2

确实如此。

延迟的是过程的输出。STDIO 进行缓冲,根据 stout 是否为终端而有所不同。

于 2013-01-23T02:29:50.160 回答