代码之家  ›  专栏  ›  技术社区  ›  vitaut

为什么子流程的输出顺序不对?

  •  0
  • vitaut  · 技术社区  · 14 年前

    我有一个Java程序 sh 以交互模式作为子进程。输入是从 System.in 输出被复制到 System.out . 一切都很好,除了在运行诸如 pwd 在这个交互式shell中,输出以错误的顺序出现,例如:

    $ pwd
    $ /home/viz/workspace
    

    而不是

    $ pwd
    /home/viz/workspace
    $
    

    区别在于在第一种情况下 $ 在输出之前打印 普华永道 .

    你知道为什么会发生这种情况以及如何解决吗?

    代码如下:

    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 回复  |  直到 14 年前
        1
  •  1
  •   khachik    14 年前

    因为标准错误和标准输出会转到不同的线程,这些线程会异步打印读取的数据。如果你重新定向 2>&1 ,但我不确定它是否适用 Runtime.exec (可能导致“找不到文件-2>&1”)。所以你可以制作一个shell脚本来调用 sh 并重定向其输出,并使用 运行时.exec :

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

    Runtime.exec("customsh");