【发布时间】:2011-04-08 04:06:24
【问题描述】:
我正在尝试执行一个新进程并从 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$
【问题讨论】:
-
很高兴看到人们在问题中使用断言而不是
System.out -
我认为这是因为程序执行打印而不是 println..
-
问题是什么?有什么问题?
标签: java process runtime cygwin inputstream