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

发布于 2024-10-03 00:53:14 字数 1811 浏览 3 评论 0原文

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

$ pwd
$ /home/viz/workspace

而不是

$ pwd
/home/viz/workspace
$

区别在于,在第一种情况下,提示符 $< /code> 在 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();
    }
}

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)
            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();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生生漫 2024-10-10 00:53:14

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

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

Runtime.exec("customsh"); 

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"); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文