为什么子进程的输出顺序错误?

时间:2010-11-18 15:42:40

标签: java linux process stream

我有一个Java程序,它以交互模式执行sh作为子进程。输入从System.in复制,输出复制到System.out。一切正常,但在此交互式shell中运行pwd等命令时,输出的顺序错误,例如:

$ pwd
$ /home/viz/workspace

而不是

$ pwd
/home/viz/workspace
$

不同之处在于,在第一种情况下,在$的输出之前打印了提示pwd

任何想法为什么会发生以及如何解决?

以下是代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

class StreamCopier implements Runnable {
    private InputStream in;
    private OutputStream out;

    public StreamCopier(InputStream in, OutputStream out) {
        this.in = in;
        this.out = out;
    }

    public void run() {
        try {
            int n;
            byte[] buffer = new byte[4096];
            while ((n = in.read(buffer)) != -1) {
                out.write(buffer, 0, n);
                out.flush();
            }
            out.close();
        }
        catch (IOException e) {
            System.out.println(e);
        }
    }
}

public class Test {
    public static void main(String[] args)
            throws IOException, InterruptedException {
        Process process = Runtime.getRuntime().exec("sh -i +m");
        Thread outThread = new Thread(new StreamCopier(
                process.getInputStream(), System.out));
        outThread.start();
        Thread errThread = new Thread(new StreamCopier(
                process.getErrorStream(), System.err));
        errThread.start();
        Thread inThread = new Thread(new StreamCopier(
                System.in, process.getOutputStream()));
        inThread.start();
        process.waitFor();
        outThread.join();
        errThread.join();
        inThread.join();
    }
}

1 个答案:

答案 0 :(得分:1)

因为标准错误和标准输出转到不同的线程,它们异步打印读取数据。如果您重定向2>&1,它可能会有效,但我不确定它是否适用于Runtime.exec(可能会导致“找不到文件 - 2>& 1”)。因此,您可以创建一个调用sh并重定向其输出的shell脚本,并使用Runtime.exec调用该脚本:

#!/bin/sh
sh -i +m 2>&1

Runtime.exec("customsh");