Я пытаюсь запустить Perl-программу из кода Java, например:
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);
}
Как видите, япотребляет выходные данные и потоки ошибок, а также закрывает стандартный ввод в соответствии с рекомендациями Здесь .
Я заметил следующее:
- Программа perl, если она запускается сама по себе, не зависает.
- Если программа perl запускается из java, оназависает, ничего не печатая из программы perl.
- Однако, это работает, если я добавлю $ | ++ в скрипт perl вверху.У меня сложилось впечатление, что новая строка в выражении perl print также должна очистить буферы, но, похоже, этого не происходит, или я что-то упустил.
- Если убрать сон - снова работает.
Я в тупике, я сделал все, что было предложено в ссылках, которые я нашел до сих пор ... Кто-нибудь может дать мне указатель здесь?Здесь есть некоторая комбинация сна и буферов, которая, кажется, приводит к сбою.