如何在父进程中拦截子进程的输出

时间:2011-09-20 04:44:46

标签: java process

我已经有一个java程序使用log4j在控制台上写输出,而现在我想使用另一个java程序来调用第一个(子进程)并拦截其输出。 我使用此页http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4中的方法,有些代码如下

class StreamRedirector extends Thread
{
InputStream is;

StreamRedirector(InputStream is)
{
    this.is = is;
}

public void run()
{
    try
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line=null;
        while ( (line = br.readLine()) != null)
        {
            System.out.println(line);
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}
}
.............
try
    {
        Process p = Runtime.getRuntime().exec("run.bat");

        StreamRedirector errSR = new StreamRedirector(p.getErrorStream());

        StreamRedirector outSR = new StreamRedirector(p.getInputStream());

        errSR.run();
        outSR.run();

        int exitVal = p.waitFor();
        System.out.println("Exit Value: " + exitVal);
    }

log4j config:
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">

    <param name="Target" value="System.out" />

    <layout class="org.apache.log4j.PatternLayout">

        <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p  [%t] [%c{1}] %m%n" />
    </layout>
</appender>

我可以使用 echo XXX 获取输出消息,但只能在“run.bat”中,而不是log4j生成的消息。如果我运行“run.bat”,我可以在控制台中看到两个输出。有没有办法让我在父进程中获得log4j输出?感谢。

1 个答案:

答案 0 :(得分:1)

StreamRedirector延伸Thread,但您致电run而非start。这意味着在调用线程中同步调用run。这意味着在以下

    errSR.run();
    outSR.run();

第二行在第一行完成之前不会执行。我猜如果错误流没有产生太多输出,那么它最终会完成。但这真的是你打算做的吗?而是尝试

    errSR.start();
    outSR.start();

如果程序正在使用log4j,我建议您考虑SocketAppender从其他进程中获取写入的内容。

EIDT:另一种方法是StreamRedirector扩展Runnable而不是Thread。然后调用代码变为

Thread errorThread = new Thread(new StreamRedirector(p.getErrorStream()));
....
errorThread.start();

这不会阻止你调用errorThread.run(),但是如果你确实调用了它,那么它会立即返回(而不是像目前那样阻塞),这表明出现了问题。