2013-01-22 44 views
3

我試圖使用ProcessBuilder在Linux中運行一些外部命令,如ifstatvmstat爲什麼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會延遲顯示頭像?

+2

ISR讀取你得到的任何東西。比較運行'ifstat 20 |貓「,以便寫入管道而不是控制檯。 –

+0

@PeterLawrey所以這是一個管道問題?其實我需要在現實世界的環境中運行'ifstat 120' ... – coolcfan

+1

數據似乎沒有被延遲,只有標題。 –

回答

2

它的確如此。

這是延遲過程的輸出。 STDIO會進行緩衝,根據粗壯或不是終端而變化。

+0

無論如何要克服這一點? – coolcfan

+2

@coolcfan fflush()在C程序中。沒有什麼可以從外面做的。 – EJP

+0

謝謝。公認。 – coolcfan

相關問題