java - 使用 Process builder 从 Java 进程调用的 Perl 脚本挂起(消耗错误,在单独的线程中输出流)
问题描述
我正在尝试从这样的 Java 代码运行 perl 程序:
package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PerlExecutor {
static ExecutorService pool = Executors.newFixedThreadPool(3);
public static void main(String[] args) throws Exception {
System.out.println("Running perl script " + args[0]);
executeProcess(args[0]);
System.out.println("Done running perl script");
pool.shutdownNow();
}
private static void executeProcess(String perlScript) throws Exception {
System.out.println("Execute process " + perlScript);
String[] command = new String[]{"perl", perlScript};
ProcessBuilder pb = new ProcessBuilder(command);
final Process process = pb.start();
process.getOutputStream().close();
Callable<Integer> callable = new Callable<Integer>() {
public Integer call() throws Exception {
int exitCode = process.waitFor();
return (Integer) exitCode;
}
};
Callable<Boolean> taskOutputStreamCallable = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
System.out.println("OutputStreamCallable started");
readStream(process.getInputStream(), "OUT");
System.out.println("OutputStreamCallable finished");
return true;
}
};
Callable<Boolean> taskErrorStreamCallable = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
System.out.println("ErrorStreamCallable started");
readStream(process.getErrorStream(), "ERR");
System.out.println("ErrorStreamCallable finished");
return true;
}
};
pool.submit(taskErrorStreamCallable);
pool.submit(taskOutputStreamCallable);
Future<Integer> f = pool.submit(callable);
f.get();
}
private static void readStream(InputStream inputStream, String type) throws
IOException {
System.out.println("Reading stream " + type);
try {
int data = inputStream.read();
System.out.println((char) data);
while (data != -1) {
System.out.println((char) data);
data = inputStream.read();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
inputStream.close();
}
System.out.println("finished reading stream");
}
}
这是我的 perl 代码:
#!/usr/local/bin/perl
print "task START \n";
$a = 10;
while(1) {
print "Value of a: $a\n";
$a = $a + 1;
sleep(10);
}
如您所见,我已经消耗了输出和错误流,并按照建议关闭了标准输入Here。
我注意到的是:
- perl 程序如果单独运行,则不会挂起。
- 如果 perl 程序是从 java 运行的,它会挂起而不会从 perl 程序中打印任何内容。
- 但是,如果我在顶部的 perl 脚本中添加 $|++ ,它会起作用。我的印象是 perl 打印语句中的换行符也应该刷新缓冲区,但显然这似乎没有发生,或者我错过了一些东西。
- 如果我取消睡眠 - 它再次起作用。
我被难住了,我已经完成了到目前为止我找到的链接中建议的所有内容..有人可以在这里给我指点吗?这里有一些 sleep 和 buffers 的组合似乎导致它失败。
解决方案
推荐阅读
- java - 我想制作一个程序来识别英雄联盟客户端中的按钮
- c++ - 如何用空格填充字符串达到一定限制?
- mongodb - 如何在 CollectionType 中的表单事件中获取数据?
- c++ - 不能包括
使用 nixos 派生的标头 - php - Symfony 4“连接被拒绝”,同时尝试连接到 docker mysql 容器
- excel - 将excel中的特定单元格添加到电子邮件正文VBA excel
- javascript - 为什么这些报价在那里,我该如何删除它们?
- java - Spring Data 和 Oracle 从查询返回不同的结果?为什么?
- javascript - npm 不会启动反应应用程序,需要依赖项:“webpack-dev-server”:“3.1.14”
- javascript - 有没有更有效的方法来对对象中的数组中的数组进行排序?