【问题标题】:Starting a process with inherited stdin/stdout/stderr in Java 6在 Java 6 中使用继承的 stdin/stdout/stderr 启动进程
【发布时间】:2010-09-08 18:52:28
【问题描述】:

如果我通过 Java 的 ProcessBuilder 类启动一个进程,我可以完全访问该进程的标准输入、标准输出和标准错误流,如 Java InputStreams 和 OutputStreams。但是,我找不到将这些流无缝连接到System.in、System.out 和System.err 的方法。

可以使用redirectErrorStream() 获取包含子进程的标准输出和标准错误的单个InputStream,然后循环并通过我的标准输出发送它——但我找不到办法并让用户输入进程,如果我使用 C system() 调用,他或她就可以。

当 Java SE 7 出现时,这似乎是可能的——我只是想知道现在是否有解决方法。如果子进程中isatty()的结果进行重定向,则加分。

【问题讨论】:

  • 非常好——我也在寻找如何做到这一点。 耶 Stackoverflow :)

标签: java io process pipe


【解决方案1】:

您需要将Process 输出、错误和输入流复制到系统版本。最简单的方法是使用 Commons IO 包中的 IOUtils 类。 copy method 看起来正是您所需要的。复制方法调用将需要在单独的线程中。

这是基本代码:

// Assume you already have a processBuilder all configured and ready to go
final Process process = processBuilder.start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(process.getOutputStream(), System.out);
} } ).start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(process.getErrorStream(), System.err);
} } ).start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(System.in, process.getInputStream());
} } ).start();

【讨论】:

  • 不完全。 IOUtils.copy 将 InputStream 作为它的第一个参数,因此它不适用于 getOutputStream。所以它是 IOUtils.copy(process.getInputStream(), System.out);这有点令人困惑,因为 getOutputStream 实际上是通过管道连接到进程的输入。
  • 这个结构看起来不错,但我也同意 IOUtils 的参数似乎是反话。 process.getInputStream() 应该通过管道传输到标准输出(是的,它听起来倒退了)。所以虽然这个结构看起来不错,但对 IOUtils 的调用看起来不对,现在让我有点困惑......
  • 错了。这只是父子输入/输出流之间的管道数据,不会让它继承它们。例如,即使 Java 命令是在终端上启动的(C isatty() == true 或 System.console() != null),孩子也不会认为自己在终端中运行,因为它的输入/输出流是管道。这很重要,因为某些(大多数)程序在终端中运行时的行为不同。 Java 7 的 ProcessBuilder.Redirect.INHERIT 在这方面可以正常工作。
【解决方案2】:

John 答案的变体,可以编译并且不需要您使用 Commons IO:

private static void pipeOutput(Process process) {
    pipe(process.getErrorStream(), System.err);
    pipe(process.getInputStream(), System.out);
}

private static void pipe(final InputStream src, final PrintStream dest) {
    new Thread(new Runnable() {
        public void run() {
            try {
                byte[] buffer = new byte[1024];
                for (int n = 0; n != -1; n = src.read(buffer)) {
                    dest.write(buffer, 0, n);
                }
            } catch (IOException e) { // just exit
            }
        }
    }).start();
}

【讨论】:

  • 不回答 System.in 的问题。
  • 为什么 pipe(System.in, process.getOutputStream());好像不行?
【解决方案3】:

对于System.in,请使用以下pipein() 而不是pipe()

pipein(System.in, p.getOutputStream());

实施:

private static void pipein(final InputStream src, final OutputStream dest) {

    new Thread(new Runnable() {
        public void run() {
            try {
               int ret = -1;
               while ((ret = System.in.read()) != -1) {
                  dest.write(ret);
                  dest.flush();
               }
            } catch (IOException e) { // just exit
            }
        }
    }).start();

}

【讨论】:

    猜你喜欢
    • 2017-07-14
    • 2013-11-08
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多