Perl-скрипт, вызываемый из процесса Java с использованием зависания компоновщика процессов (ошибка потребления, потоки вывода в отдельных потоках) - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь запустить 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);
}

Как видите, япотребляет выходные данные и потоки ошибок, а также закрывает стандартный ввод в соответствии с рекомендациями Здесь .

Я заметил следующее:

  1. Программа perl, если она запускается сама по себе, не зависает.
  2. Если программа perl запускается из java, оназависает, ничего не печатая из программы perl.
  3. Однако, это работает, если я добавлю $ | ++ в скрипт perl вверху.У меня сложилось впечатление, что новая строка в выражении perl print также должна очистить буферы, но, похоже, этого не происходит, или я что-то упустил.
  4. Если убрать сон - снова работает.

Я в тупике, я сделал все, что было предложено в ссылках, которые я нашел до сих пор ... Кто-нибудь может дать мне указатель здесь?Здесь есть некоторая комбинация сна и буферов, которая, кажется, приводит к сбою.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...