如何在log4j RollingFileAppender中从Java中启动的Shell脚本输出日志?

时间:2011-11-22 17:23:31

标签: java shell logging log4j echo

我在Tomcat上运行Java Web应用程序,在运行时执行Shell脚本,执行许多“echo”命令。

我的问题是我希望我的所有日​​志都出现在log4j RollingFileAppender中,即:

  • Java Log4j日志(很容易做到)
  • Shell echo命令日志(这对我来说很棘手)

Shell脚本通过java.lang.Process类运行。 到目前为止,由于log4j提供的StreamUtils.copy()方法,我已设法将进程的inputStream和errorStream输出到System.out。

但是这样可以获得一些ConsoleAppender输出,但不是RollingFileAppender输出。

有没有方便的方法将Process流重定向到RollingFileAppender?在Log4j配置中还是从Java代码?

这是我的LOG4J appender conf:

<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out" />
    <param name="Threshold" value="DEBUG" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{ABSOLUTE} [%-20.20t] %-5p [%-25.25c{1}] - %m%n" />
    </layout>
</appender>

<appender name="FILE" class="org.apache.log4j.RollingFileAppender">
    <param name="Threshold" value="DEBUG" />
    <param name="File" value="&LOG_DIR;/&PROJECT_NAME;.log" />
    <param name="Append" value="&APPEND;" />
    <param name="MaxFileSize" value="&MAX_SIZE;" />
    <param name="MaxBackupIndex" value="&MAX_BACKUP;" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{ISO8601} | &#x25;-21.21X{applicationId}|  %-40.40t| %-5p |%-25.25c{1}| - %m%n" />
    </layout>
</appender>

这是我的启动脚本代码:

    ProcessBuilder pb = new ProcessBuilder("sh", "script.sh");
    Process p = pb.start();
    StreamUtils.copy(p.getInputStream(), System.out);
    StreamUtils.copy(p.getErrorStream(), System.out);
    int result = p.waitFor();
    LOG.info("Script ended with result " + result);
    return (result == 0);

2 个答案:

答案 0 :(得分:3)

以下是我用来记录流程输出的代码片段。很简单,似乎工作。谢谢@mezzie。

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

import org.apache.log4j.Logger;

public class ProcessLoggerThread extends Thread {

private final static Logger LOGGER = Logger.getLogger(ProcessLoggerThread.class);

private InputStream inputStream;


public ProcessLoggerThread(InputStream inputStream) {
    super();

    this.inputStream = inputStream;
}


public void run() {
    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line = reader.readLine();
        while (line != null) {
            LOGGER.debug(line);
            line = reader.readLine();
        }
        reader.close();
        LOGGER.debug("End of logs");
    } catch (IOException e) {
        LOGGER.error("The log reader died unexpectedly.");
    }
}
}

答案 1 :(得分:1)

你在使用线程吗?如果是这样,您需要查看https://stackoverflow.com/q/8229913/458901以使其与滚动的appender一起使用。

与此相关,您的线程可以使用此方法来传递字符串数组(如果有的话,使用args命令),并返回该命令的输出。当然,只需使用它返回的字符串添加到日志中:)

private String execute(String[] command){
    //System.out.println(command);
    try{
        process = Runtime.getRuntime().exec(command);
        InputStream istream = process.getInputStream();
        Writer writer = new StringWriter();
        char[] buffer = new char[1024];
        Reader reader = new BufferedReader(new InputStreamReader( istream ));
        int n;
        while ((n = reader.read(buffer)) != -1) {
            writer.write(buffer, 0, n);
        }
        reader.close();
        istream.close();
        return writer.toString();
    }
    catch ( IOException e )
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return "";
}

}