gpt4 book ai didi

java - 当设置为父级的标准 IO(命令提示符)时,Windows Java 子进程不输入或输出

转载 作者:可可西里 更新时间:2023-11-01 12:44:07 24 4
gpt4 key购买 nike

在 Windows 下,当我的程序从命令行启动时,我无法可靠地操作我的子进程的 I/O。令人沮丧的是,服务器使用控制台进行 I/O 是标准做法。图形用户界面很好,但我真的更喜欢坚持使用命令行并保持简单。我注意到当我从 Eclipse IDE 执行我的服务器时,子进程 I/O 很好,但是从命令行运行就完全不同了。我无法读取或写入子进程,但该进程仍在运行。我在下面写了一些测试代码来演示这个问题,我希望这个问题可以在另一台机器上重现,然后希望从中得到解决方案。从 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 session 运行它,所有子进程的 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”文件,然后崩溃或被操作系统停止。实际测试本身没有变化,只是测试现在允许您输入在运行时运行的命令。这在 linux 中工作正常,但在 windows 中不行。我希望了解 Win32 API 的人能够以某种方式解释为什么此测试在 Windows 中失败。

最佳答案

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

在我看来,您需要为 Windows 上的输入/输出流提供服务。这篇文章是关于 Runtime.exec 的,但我敢打赌 ProcessBuilder 的 native 代码非常相似,并且在 Windows 上存在相同类型的问题。

我猜测为什么这在 Windows 上的 Eclipse 上有效,因为 Eclipse 代表您为流提供服务,以便在控制台 View 中显示内容。

关于java - 当设置为父级的标准 IO(命令提示符)时,Windows Java 子进程不输入或输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10671081/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com