当设置为父母的标准IO(命令提示符)的Windows的Java子进程没有输入或输出(Windows

2019-06-24 14:47发布

在Windows下,我无法可靠地处理我的子进程时,我的方案已经通过命令行启动的I / O。 这是令人沮丧,因为它是标准的服务器使用一个控制台I / O。 图形用户界面是好的,但我真的喜欢粘到命令行,并让事情变得简单。 我注意到,子进程I / O是蛮好的,当我从Eclipse IDE执行我的服务器,但它是一个完全不同的故事是在命令行中运行。 我无法读取或写入的子进程,但这一过程仍然会运行。 我已经写了下面的一些测试代码演示了此问题,并且我希望这个问题能够在另一台机器上进行复制,然后希望得到一个解决方案出来。 当从Eclipse的执行,继承了I / O工作正常。 然而,从Windows命令提示符下执行时,没有什么可以读取或写入的子进程。 在这两种情况下,子进程输出重定向到一个文件总是成功,但输入仍然不能传递给孩子。 如果已经有这个问题的解决方案,那么请链接的网页。

JRE / JDK实现:

>java -version
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)

考虑下面的代码:

package com.comp8nerd4u2.io.test;

/*
 * These tests attempt to confirm what I'm experiencing under my build environment
 */

import java.io.File;
import java.io.IOException;

public final class PIOTest {

/** The command to run as a child process. The command itself isn't the test, but what you use to run this Java program is the test. */
private static final String[] COMMAND = {"cmd.exe", "/c", "echo This is a test. Feel free to change this."}; // Change this to just {"cmd.exe"} or some other program that accepts input and you'll see how frustrating this is
/** Controls how the test process is built */
private static final ProcessBuilder PB = new ProcessBuilder(COMMAND);
/** How long to allow the process to run before forcibly terminating it. */
private static final long PROCESS_TIMEOUT = 10000L;
private static final Runnable R = new TimedInterruptWorker(PROCESS_TIMEOUT);

private static int n = 0;

static {
    PB.redirectErrorStream(true);
}

private PIOTest() {}

public static void main(String[] args) {

    // ----- Begin Tests -----

    /*
     * Test #1: Let's test putting our command's output onto our standard I/O streams
     * Goal condition: Child process outputs expected output, and exits before the timeout. If child process expects input, it should accept entered input.
     * Known success factors: Parent process' standard I/O is piped to Eclipse. Tests would probably succeed with Netbeans as well
     * Known fail factors: Parent process' standard I/O is piped to Windows Command Prompt
     * Result under fail condition: Child process hangs if it fills up its output buffer or requests input, but exits on its own otherwise, unless it took longer than the timeout. 
     */
    PB.inheritIO();
    doTest();

    // Test #2: Let's test putting our command's output into a file
    PB.redirectOutput(new File("piotest.txt"));
    doTest();
}

/**
 * Performs the I/O test.
 */
private static void doTest() {
    n++;
    Process p = null;
    try {
        p = PB.start();
    } catch (IOException e) {
        e.printStackTrace();
        return;
    }
    try {
        Thread t = new Thread(R);
        t.setDaemon(true);
        t.start();
        System.out.format("[Test #%d] Child exited with status code %d\n", n, p.waitFor());
        t.interrupt();
    } catch (InterruptedException e) {
        p.destroy();
        System.out.format("[Test #%d] Child took longer than the timeout.\n", n);
    }
}

/**
 * Useful for sending interrupts after a certain amount of time has passed.
 * 
 * @author comp8nerd4u2
 */
private static final class TimedInterruptWorker implements Runnable {

    private long timeout = 0;
    private Thread target = null;

    public TimedInterruptWorker(long timeout) {
        this(timeout, Thread.currentThread());
    }

    public TimedInterruptWorker(long timeout, Thread target) {
        this.timeout = timeout;
        this.target = target;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(timeout);
        } catch (InterruptedException e) {
            return;
        }
        target.interrupt();
    }

}

}

更新:我修改了测试,以接受在运行任何命令,并将其上传到我的Linux VPS服务器。 我从一个SSH会话运行它和所有的子进程的I / O可以读取和轻松写入。 还有的是,我注意到一两件事。 当我打开一个交互式的bash shell作为一个子进程,然后重定向它的输出到一个文件,CentOS的停在我的计划,我想。 这还是我的程序崩溃。

[admin@comp8nerd4u2 piotest]$ java -jar piotest.jar
Enter command to run : bash
[admin@comp8nerd4u2 piotest]$ [Test #1] Child took longer than the timeout.

[1]+  Stopped                 java -jar piotest.jar
[admin@comp8nerd4u2 piotest]$

第一行是我的命令输入。 第二行是被催生bash shell的,但让我的节目超时后杀死它,我从来没有录入任何进去。 它准备好了第二次测试,创建“piotest.txt”文件,然后要么崩溃或由OS停止。 实际测试本身是不变的,只是现在的测试可以让你输入什么命令,在运行时运行。 这在Linux中正常工作,但不是在Windows。 我希望有人谁知道在Win32 API可以以某种方式解释为什么本次测试在Windows中失败。

Answer 1:

你看过这篇文章? http://www.javaworld.com/jw-12-2000/jw-1229-traps.html?page=1

像你需要服务Windows上的输入/输出流这听起来我。 这篇文章是关于的Runtime.exec,但我打赌的ProcessBuilder本机代码非常相似,并且具有相同类型的Windows上的问题。

我为什么这适用于Eclipse的Windows上的猜测是,Eclipse正在服务代表您的流,才能在控制台视图中显示的东西。



Answer 2:

我知道我在回答晚了,但我碰到这个问题,遇到了答案来临前,想救别人在同一条船上一些搜索。

这实际上是一个Windows的已知的bug: https://bugs.openjdk.java.net/browse/JDK-8023130

您可以通过重定向数据流自己绕过它:

Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
   System.out.println(line);
}

p.waitFor();

br.close();


文章来源: Windows Java child process doesn't input or output when set to parent's standard IO (Command Prompt)
标签: java windows cmd