Как выводить журналы из сценария оболочки, запущенного в Java, в log4j RollingFileAppender?

У меня есть веб-приложение Java, работающее на Tomcat, выполняющее сценарии оболочки во время выполнения, в котором выполняются многие команды «эхо».

Моя проблема в том, что я хочу, чтобы все мои журналы отображались в log4j RollingFileAppender, то есть:

  • Журналы Java Log4j (что легко сделать)
  • Журналы эхо-команд оболочки (что для меня сложно)

Сценарии оболочки запускаются через класс java.lang.Process. До сих пор мне удавалось выводить inputStream и errorStream процесса в System.out благодаря предоставленному log4j методу StreamUtils.copy().

Но тогда это нормально, чтобы получить некоторый вывод ConsoleAppender, но не вывод RollingFileAppender.

Есть ли удобный способ перенаправить потоки процессов в RollingFileAppender? В конфигурации Log4j или из кода Java?

Вот моя конфигурация приложения LOG4J:

<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);

person Dirty Henry    schedule 22.11.2011    source источник


Ответы (2)


Вы используете нить? если это так, вам нужно увидеть https://stackoverflow.com/q/8229913/458901, чтобы он работал с прокаткой приложения.

В сочетании с этим ваш поток может использовать этот метод, который вы можете использовать для передачи массива строк (ваша команда с аргументами, если они есть), и вернет вам вывод этой команды. Конечно, просто используйте строку, которую он возвращает, чтобы добавить в свой журнал :)

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 "";
}

}

person mezzie    schedule 22.11.2011
comment
Спасибо, меня вдохновил ваш ответ (см. мой собственный ответ для кода). Странно, однако, что это не стандартная функция log4j. Если вокруг люди Apache... ;) - person Dirty Henry; 01.12.2011

Вот фрагмент кода, который я использовал для регистрации результатов моего процесса. Довольно просто и, кажется, работает. Спасибо @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.");
    }
}
}
person Dirty Henry    schedule 01.12.2011