我試圖使用ProcessBuilder
在Linux中運行一些外部命令,如ifstat
或vmstat
。爲什麼InputStreamReader不能實時讀取進程的輸出?
這種類型的命令支持自定義採樣間隔。如果我一個採樣間隔添加到外部命令,例如,ifstat 20
,則命令將這樣輸出:
[email protected]:~$ 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秒)
而且我注意到輸出延遲的長度與間隔I設置爲該命令。
那麼,爲什麼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
會延遲顯示頭像?
ISR讀取你得到的任何東西。比較運行'ifstat 20 |貓「,以便寫入管道而不是控制檯。 –
@PeterLawrey所以這是一個管道問題?其實我需要在現實世界的環境中運行'ifstat 120' ... – coolcfan
數據似乎沒有被延遲,只有標題。 –