How to output logs from a Shell Script launched wi

2019-05-05 03:20发布

I have a Java Webapplication running on Tomcat, executing Shell scripts at runtime in which many "echo" commands are executed.

My problem is that I'd like all my logs to appear in a log4j RollingFileAppender, ie:

  • Java Log4j logs (which is easy to do)
  • Shell echo commands logs as well (which is the tricky part to me)

The Shell scripts are run via java.lang.Process class. So far, I've managed to output the inputStream and errorStream of the process to System.out thanks to the log4j-provided StreamUtils.copy() method.

But then this is fine to get some ConsoleAppender output, but not a RollingFileAppender output.

Is there any convenient way to redirect the Process streams to a RollingFileAppender? In Log4j configuration or from the Java code?

Here is my 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>

Here is my launching script code:

    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条回答
时光不老,我们不散
2楼-- · 2019-05-05 03:54

Are you using a thread? if so, you need to see https://stackoverflow.com/q/8229913/458901 to make it work with rolling appenders.

In conjunction with that, your thread can use this method that you can use to pass in a string array (your command with args if any) and will return you the output of that command. Of course, just use the string it returns to add to your log :)

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

}

查看更多
叼着烟拽天下
3楼-- · 2019-05-05 04:05

Here is the snippet of code I've used to log the output of my process. Pretty straightforward and seems to work. Thanks @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.");
    }
}
}
查看更多
登录 后发表回答