【发布时间】:2013-01-05 13:38:13
【问题描述】:
我正在尝试使用 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 不实时读取输出呢?
一个简单的测试代码sn-p来演示我的问题:
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会延迟显示头像?
【问题讨论】:
-
ISR 读取你得到的任何东西。为了比较,运行
ifstat 20 | cat以便它写入管道而不是控制台。 -
@PeterLawrey 所以这是管道问题?其实我需要在现实环境中运行
ifstat 120... -
数据似乎没有延迟,只有标题。
-
@PeterLawrey 好的,好吧,是的.. 但是为什么头部延迟显示?
-
我怀疑它没有明确刷新。写入控制台时会自动刷新,但写入管道时需要显式刷新,直到出现第一行数据。
标签: java process io inputstream