我正在尝试使用ProcessBuilder
来运行一些外部命令,例如Linux中的ifstat
或vmstat
。
此类命令支持自定义采样间隔。如果我向外部命令添加一个采样间隔,例如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
会延迟显示头部?
答案 0 :(得分:2)
确实如此。
该进程的输出被延迟。 STDIO做缓冲,根据粗壮或不是终端而变化。