2012-09-18 48 views
0

我創建了一個具有2個Jar文件的Java應用程序。 Jar1用來初始化和運行Jar2,使用此代碼:如何逐行打印來自另一個罐子的日誌?

Process process = runtime.exec("java -jar Jar2.jar"); 
printLogs(process); 
. 
. 
. 
private static boolean printLogs(Process process) { 
    try { 
     BufferedInputStream logStream = new BufferedInputStream(process.getInputStream()); 
     String logs = ""; 
     int buffer = 0; 

     while ((buffer = logStream.read()) != -1) { 
      logs += (char)buffer; 
     } 

     if(!logs.isEmpty()) logger.debug(logs); 
    } catch (IOException e) {} 

    return true; 
} 

我打印使用的Log4J從Jar2許多日誌,即

logger.debug("..."); 

但沒有在Jar2日誌被打印到控制檯。我想到這是因爲日誌被返回到Jar1而不是控制檯,所以我使用上面的代碼打印返回的流。日誌現在可以正常打印,但畢竟Jar2過程結束了,所有日誌都會在Jar1中立即打印。

問題是:我可以在Jar2中打印每個日誌行,而不是等待所有Jar2進程結束嗎?

由於Jar2是一個漫長的過程,在應用程序處理過程中我可以看到這些日誌非常重要。

回答

0

您的代碼似乎在實際寫入日誌(在進程退出時發生)之前似乎正在等待logStream到達EOF。嘗試重構它逐字符讀取它,然後每當看到換行符時記錄累積的字符緩衝區(當然,因此您可以獲得最後一行)。

2

整件事相當混亂。您不應該需要兩個單獨的檔案並且Runtime.exec()

但是,通常使用BufferedReader.readLines來讀取文本行。請注意,這個問題簡單地消失了,如果你登錄的那一刻每一行你讀它:

BufferedReader input = new BufferedReader(
    new InputStreamReader(process.getInputStream()) 
); 
String line = null; 

while ((line = input.readLine()) != null) { 
    System.out.println(line); 
} 

你的代碼等待子進程來完成,因爲您登錄直播結束後的行(即子進程終止後)

下面是使用長時間運行Ruby程序的觀看過程

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 

public class Subprocess { 

    static final String[] program = new String[] { 
     "ruby", 
     "-e" , 
     "(1..5).each{|i|sleep 1;puts i;STDOUT.flush}" 
    }; 

    public static void main(String[] args) throws IOException { 
     ProcessBuilder builder = new ProcessBuilder(program); 
     builder.redirectErrorStream(); 

     Process child = builder.start(); 

     String line = null; 
     BufferedReader in = new BufferedReader(
       new InputStreamReader(child.getInputStream())); 

     while ((line = in.readLine()) != null) 
      System.out.println(line); 
    } 

} 
+1

+1被搞砸了。另外,如果你直接使用System.out.println而不是'debug',那麼日誌會更簡單:否則你最終會在兩行中產生兩個時間戳等等,以及其他日誌記錄。 – artbristol

+0

良好的捕捉:)我沒想到除非他使用「空白」佈局來擺脫第二次日誌調用的格式化(這很奇怪),並且使用了其他一些appender來調試'debug()'而不是'System.out' – Raffaele

+0

主要想法是我想使用「Runtime.exec()」。我確實執行了一些必須在Jar1中的代碼。我已經試過你的代碼,但它仍然在Jar2過程完成後打印所有日誌,這是合乎邏輯的。如你所說;因爲「代碼等待子流程完成,因爲您在流結束後登錄了該行」! – Brad