我正在尝试使用ProcessBuilder
来运行一些外部命令,例如Linuxifstat
或vmstat
在 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
会延迟露头呢?