Java ProcessBuilder запускает сценарий оболочки зависает

Я пытаюсь запустить сценарий оболочки с помощью ProcessBuilder. Скрипт работает, но не может работать после кода Java. И поток ошибок не выводит сообщение. Я запускаю его на компьютере с CentOS 6.9. Пожалуйста, найдите мой код ниже.

public static ArrayList<String> runCommand(ArrayList<String> command)throws IOException {

        ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.command(command);
        Process process = processBuilder.start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        ArrayList<String> commandOutput = new ArrayList<>();
        String str;
        while((str = reader.readLine()) != null) {
            commandOutput.add(str);
        }

        StringBuilder errorBuilder = new StringBuilder();
        while((str = errorReader.readLine()) != null) {
            errorBuilder.append(str);
        }

        String errorMessage = errorBuilder.toString();
        if (!errorMessage.equals("")) {
            String message = LOG_TAG + ",[runCommand] error:" + errorMessage;
            System.out.println(message);
        }

        reader.close();
        errorReader.close();
        process.destroy();

        return commandOutput;
    }

Попробуйте использовать выходные потоки в потоках (или перенаправить ошибку через стандартный вывод и использовать один поток) и используйте waitFor на process, чтобы дождаться завершения выполнения.

MadProgrammer 07.01.2019 04:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
1
161
1

Ответы 1

В вашем случае вы читаете что-то из выходного потока процесса, пока не потребляете все. Затем вы пытаетесь прочитать поток ошибок.

Если процесс записывает значительное количество символов в поток ошибок, другой процесс блокируется до тех пор, пока они не будут использованы. Чтобы одновременно использовать поток ошибок и поток вывода, необходимо использовать потоки.

Вы можете следовать методике StreamGobbler. Вы можете получить некоторые подробности на этой странице: https://www.javaworld.com/article/2071275/when-runtime-exec---won-t.html?page=2

Это код, на который повлияла страница:

public class StreamGobbler extends Thread {
    private static final String EOL = System.lineSeparator();
    private final InputStream inputStream;
    private final StringBuilder output = new StringBuilder();

    public StreamGobbler(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public void run() {
        try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
             BufferedReader reader = new BufferedReader(inputStreamReader);
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line);
                output.append(EOL);
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public String getOutput() {
        return output.toString();
    }
}

В вашем коде вы используете StreamGobbler следующим образом:

    StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream());
    StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream());

    process.waitFor();

    String commandOutput = outputGobbler.getOutput();
    String errorMessage = errorGobbler.getOutput();
    process.destroy();

Другие вопросы по теме