java子进程在终止之前不会写入其输出 [英] java subprocess does not write its output until it terminates

查看:162
本文介绍了java子进程在终止之前不会写入其输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了这个简单的测试用例来描述我遇到的问题:

I've written this simple testcase that describes the problem I'm having:

我从Java创建一个子进程,同时启动一个应该每个都写的线程从子进程'标准输出中读取它后行。

I create a subprocess from Java, and simultaneously start a thread that SHOULD write every line as soon as it is read from subprocess' standard output.

我得到的是子进程'输出在终止时完全写入。以下是输出:

What I get instead is that the subprocess' output is entirely written when it terminates. Here is the output:

Mon Jul 15 19:17:13 CEST 2013: starting process
Mon Jul 15 19:17:14 CEST 2013: process started
Mon Jul 15 19:17:14 CEST 2013: waiting for process termination
Mon Jul 15 19:17:14 CEST 2013: readerThread is starting
Mon Jul 15 19:17:19 CEST 2013: process terminated correctly
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(7)
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(49)
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(73)
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(58)
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(30)
Mon Jul 15 19:17:19 CEST 2013: readerThread is terminating

使用此代码:

public class MiniTest {
    static void println(String x) {
        System.out.println(new Date() + ": " + x);
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder pb = new ProcessBuilder("bin/dummy", "foo", "5");

        println("starting process");
        Process p = pb.start();
        println("process started");

        new ReaderThread(p).start();

        println("waiting for process termination");
        p.waitFor();
        println("process terminated correctly");
    }

    static class ReaderThread extends Thread {
        private Process p;

        public ReaderThread(Process p) {
            this.p = p;
        }

        public void run() {
            println("readerThread is starting");
            BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            try {
                while((line = r.readLine()) != null) {
                    println(this + " got line: " + line);
                }
            } catch(IOException e) {
                println("read error: " + e);
            }
            println("readerThread is terminating");
        }
    }
}

注意:子流程非常简单地说,它每秒输出一行,用于指定的迭代次数(当在命令行上测试时,它会这样做):

Note: the subprocess is very simple, it outputs a line every second, for a specified abount of iterations (and when tested on the command line, it does so):

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    char *f = argv[1];
    int n = atoi(argv[2]);
    while(n-- > 0) {
        printf("%s(%d)\n", f, rand() % 100);
        sleep(1);
    }
    return 0;
}


推荐答案

通过询问找到答案研究这个问题。

Found the answer by asking around and studying on the issue.

问题不容易解决,但显然这是一个libc问题。如果输出不是tty / pty,则缓冲不是一行的。

The problem cannot be easily solved, but apparently it's a libc issue. If the output it's not a tty/pty, the buffering is not by line.

有外部程序或脚本可以解决这个问题,比如stdbuf或者unbuffer(来自期待)。

There are external programs or script however that allow to work around this, like for example stdbuf or unbuffer (from expect).

详细说明:在管道到发球台时强制线缓冲标准杆

这篇关于java子进程在终止之前不会写入其输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆