开发者

Why is the output from subprocess in wrong order?

开发者 https://www.devze.com 2023-01-25 14:18 出处:网络
I have a Java program that executes sh in interactive mode as a subprocess. The input is copied from System.in and output is copied to System.out. Everything works fine except that when running comman

I have a Java program that executes sh in interactive mode as a subprocess. The input is copied from System.in and output is copied to System.out. Everything works fine except that when running commands such as pwd in this interactive shell the output appears in a wrong order, for example:

$ pwd
$ /home/viz/workspace

instead of

$ pwd
/home/viz/workspace
$

The difference is that in the first case the prompt $ is printed before the output from pwd.

Any ideas why does it happen and how to fix it?

Here is the code:

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)
            th开发者_如何学Pythonrows 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();
    }
}


Because standard error and standard output go to different threads which print the read data asynchronously. It might work, if you redirect 2>&1, but I'm not sure it will work with Runtime.exec (may cause "file not found - 2>&1"). So you can make a shell script which calls sh and redirects its output, and call that script using Runtime.exec:

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

and

Runtime.exec("customsh"); 
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号