好的 - 这对很多人来说都是一个问题 - 因为我还没有看到一个有效的答案,我想我会表达这个问题,所以找到它的人可以告诉我们其他人
问题是以下三个中的两个工作只是很好的相同代码。
reader3的实例演示了这个问题。 Reader3无法读取成功启动外部文件的结果。尝试在stdin或stderr InputStream上永久阻止任何类型的读取(realine等):
package Problems;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RunningProblem {
public static class RunningReader implements Runnable {
private Process proc;
private String sName;
private RunningReader(Process proc1, String sName) {
this.proc = proc1;
this.sName = sName;
}
public void run() {
try {
// InputStreamReader in = new InputStreamReader(proc.getInputStream());
// BufferedReader reader = new BufferedReader(in);
InputStreamReader err = new InputStreamReader(proc.getErrorStream());
BufferedReader reader = new BufferedReader(err);
String line = reader.readLine();
while (line != null) {
System.out.println(sName + ": " + line);
line = reader.readLine();
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
try {
Runtime rt = Runtime.getRuntime();
Process proc1 = rt.exec("ps ax");
RunningReader reader1 = new RunningReader(proc1, "reader1");
Process proc2 = rt.exec("ls -l /");
RunningReader reader2 = new RunningReader(proc2, "reader2");
Process proc3 = rt.exec("/bin/tar");
RunningReader reader3 = new RunningReader(proc3, "reader3");
pool.execute(reader3);
pool.execute(reader2);
pool.execute(reader1);
} catch (Exception ex) {
System.err.println(ex.getMessage());
} finally {
pool.shutdown();
}
System.out.println("Launcher.main() Exited.");
}
}
答案 0 :(得分:1)
您没有显示程序产生的输出,但我想可能是这种情况,ps ax
和ls -l /
不会产生输出,但/bin/tar
会产生输出。原因是,前两个命令产生的输出为stdout
但不产生stderr
,而后者将产生stderr
的输出(因为您没有给{{1}的有效参数})但不在tar
上。
这是在shell中运行命令时的区别:
stdout
使用[axe@gromp tmp]$ ps ax > ps-std.txt 2> ps-err.txt
[axe@gromp tmp]$ ls -l / > ls-std.txt 2> ls-err.txt
[axe@gromp tmp]$ /bin/tar > tar-std.txt 2> tar-err.txt
[axe@gromp tmp]$ ls -lrt
total 18
-rw-r--r-- 1 axe users 0 Mar 5 19:40 ps-err.txt
-rw-r--r-- 1 axe users 7191 Mar 5 19:40 ps-std.txt
-rw-r--r-- 1 axe users 0 Mar 5 19:40 ls-err.txt
-rw-r--r-- 1 axe users 937 Mar 5 19:40 ls-std.txt
-rw-r--r-- 1 axe users 0 Mar 5 19:41 tar-std.txt
-rw-r--r-- 1 axe users 142 Mar 5 19:41 tar-err.txt
[axe@gromp tmp]$
重定向标准输出,>
将错误输出重定向到不同的文件,您可以看到2>
在tar
和其他两个上生成消息在stderr
上(其他文件的文件大小为零,没有输出)。
可能是这种情况吗?如果你跑步会发生什么,例如G。 stdout
代替echo "Foo"
作为第三个流程?
答案 1 :(得分:1)
我在我的系统上运行了你的代码,在正常退出之前它给了我以下输出:
reader3: /bin/tar: You must specify one of the `-Acdtrux' options reader3: Try `/bin/tar --help' or `/bin/tar --usage' for more information. Launcher.main() Exited.
ps ax
和ls -l /
没有输出,但是从shell运行它们确认它们没有写任何标准错误。在我的系统上,你的代码碰巧正常完成,但我可以想象这种情况不会发生。请注意,如果进程在其标准输出上生成大量输出,则缓冲区可能会填满,这会导致进程挂起。
我建议使用ProcessBuilder
代替。{
Runtime.getRuntime().exec("...")
。首先,它允许您将标准错误流重定向到标准输出流,然后不必担心要读取的两个流中的哪一个。
答案 2 :(得分:0)
Facinating(spockian eyebrow) - 从上面的评论来看,它看起来有很多理由说明为什么这么多人都有这方面的问题 - 我们的实现似乎各不相同!
我正在运行Ubuntu。有趣的是,使用ProcessBuilder颠倒了问题...但是至少现在没有人在使用它时“永远阻止”。 - 至少stderr和stdin能够被阅读!
所以对我来说,现在,经验法则似乎是:在Ubuntu上使用“旧方式”(Runtime.getRuntime()。exec())来命令shell('内部')命令(Oracle / Sun VM) - 使用ProcessBuilder获取外部命令(如tar等):
Process proc3 = new ProcessBuilder("/bin/tar").start();
RunningReader reader3 = new RunningReader(proc3, "reader3");
...
reader3:/ bin / tar:你必须指定 其中一个
-Acdtrux' options reader3: Try
/ bin / tar --help'或`/ bin / tar --usage'了解更多信息。
- 对于我们中的许多人来说,这是一项非常重要的操作......将一个矩阵放在哪个平台上的什么用途上会很好.... (也就是说我想知道OpenJDK在Ubuntu上会做得更好吗?)
答案 3 :(得分:-1)
你可能很晚才开始使用RunningReaders。 您启动了三个进程,在开始阅读RunningReader中的Error-OutputStream之前,有时可能已完成第一个进程。
必须在流程开始后立即启动RunningReaders。
在某些条件下,即使这可能还不够。然后你必须创建一个包装器脚本(对于每个操作系统),它捕获输出并将其写入文件。