gpt4 book ai didi

java - Runtime.getRuntime().exec ("C:\cygwin\bin\bash.exe") 没有可读取的输入

转载 作者:行者123 更新时间:2023-11-30 07:36:23 25 4
gpt4 key购买 nike

我正在尝试执行一个新进程并从它的 Java 输入流中读取。我已成功使用 Runtime.getRuntime().exec(String) 启动并接收来自多个进程的输入。但是,当我尝试在其他一些进程上使用 exec 时,输入流的 read 方法阻塞,并且似乎没有输入。是什么导致其中一些进程的输入流为空?具体来说,我想知道为什么 bash.exe 没有输出任何东西。

我已经编写了一个 JUnit 测试用例来演示这个问题:

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import junit.framework.TestCase;

public class TestExec extends TestCase {

public void testExec() throws IOException {
List<InputPrinter> threads = new ArrayList<InputPrinter>();

// Create a process for each of the commands and make sure that
// it outputs at least one line to its input stream.
threads.add(testExec("cmd"));
threads.add(testExec("java"));
threads.add(testExec("C:/cygwin/bin/vim-nox.exe"));

// These bottom two fail, even though executing these
// commands in cmd.exe results in immediate output
threads.add(testExec("javac"));
threads.add(testExec("C:/cygwin/bin/bash.exe"));

// Give the threads a second to execute
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
fail();
}

// Test that each command had input to read
for(InputPrinter ip : threads) {
assertTrue(ip.command + " has not read any input", ip.hasRead);
}
}

// Starts a process for the given command and returns an
// InputPrinter that can be used to check if the process
// has had an input to read.
public InputPrinter testExec(String command) throws IOException {
Process proc = Runtime.getRuntime().exec(command);
InputStream in = proc.getInputStream();

InputPrinter ip = new InputPrinter(in, command);
new Thread(ip).start();

return ip;
}

// Simple Runnable to read from an InputStream. hasRead will be
// true if at least one input has been read from the stream
private class InputPrinter implements Runnable {
InputStream in;
String command;
boolean hasRead;

public InputPrinter(InputStream in, String command) {
this.in = in;
this.command = command;
this.hasRead = false;
}

// Loop indefinitely while printing any received input
public void run() {
try {
final byte[] b = new byte[1024];
while (true) {
int n = in.read(b);
if (n > 0) {
System.out.print(new String(Arrays.copyOf(b, n)));
hasRead = true;
}
}
} catch (IOException e) {
e.printStackTrace();
fail();
}
}
}

}

编辑:

据我所知,如果程序不使用 stdout 或 stderr,我应该不会在 Windows 命令提示符中看到任何内容。我在启动 bash 进程时期望看到的是“bash-3.2$”,这与我在打开命令提示符并运行“bash.exe”时看到的相同:

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\cygwin\bin>bash.exe
bash-3.2$

最佳答案

不管 Java,据我所知,只有当 bash 作为脚本运行时,您才能通过管道从/向 bash 输出(或输入),而不是当它作为交互式 shell 运行时(在这种情况下,您只能通过cmd 参数)。

换句话说,当您像评论中提到的那样从 cmd 运行 bash 时,您会看到输出,但它包含在 bash 进程中,而不是 bash 发送回父 cmd 进程的输出。

关于javac进程,它实际上是将输出发送到错误流。尝试从 cmd javac 1>nulljavac 2>null 运行,您会看到不同之处。
你看过API了吗here ?您可以尝试使用 ProcessBuilder 并将错误流重定向回主输入流,以这种方式处理流程会容易得多。

关于java - Runtime.getRuntime().exec ("C:\cygwin\bin\bash.exe") 没有可读取的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3641407/

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