Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
java
runtime.exec
user590444
источник
источник
Ответы:
Есть много причин, по которым
waitFor()
он не возвращается.Но обычно все сводится к тому, что выполненная команда не завершается.
И для этого опять же может быть много причин.
Одна из частых причин заключается в том, что процесс производит некоторый вывод, а вы не читаете из соответствующих потоков. Это означает, что процесс блокируется, как только буфер заполняется, и ожидает, пока ваш процесс продолжит чтение. Ваш процесс, в свою очередь, ожидает завершения другого процесса (чего не будет, потому что он ждет вашего процесса, ...). Это классическая тупиковая ситуация.
Вам необходимо постоянно читать из входного потока процессов, чтобы убедиться, что он не блокируется.
Есть хорошая статья, которая объясняет все подводные камни
Runtime.exec()
и показывает способы их решения под названием «Когда Runtime.exec () не работает» (да, статья датируется 2000 годом, но содержание все еще применимо!)источник
waitFor()
не возвращается.Похоже, вы не читаете вывод, не дожидаясь его завершения. Это нормально, только если вывод не заполняет буфер. Если это так, он будет ждать, пока вы не прочитаете вывод, catch-22.
Возможно, у вас есть ошибки, которые вы не читаете. В этом случае приложение остановится и будет ждать вечно. Простой способ обойти это - перенаправить ошибки на обычный вывод.
источник
pb.redirectError(new File("/dev/null"));
redirectError
доступно только с Java 1.7Также из документа Java:
Попробуй это:
источник
DefaultExecutor executor = new DefaultExecutor(); PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdoutOS, stderrOS); executor.setStreamHandler(pumpStreamHandler); executor.execute(cmdLine);
где stoutOS и stderrOSBufferedOutputStream
я создал для записи в соответствующие файлы.process.close()
. Но когда я открываю поток ввода, как было предложено выше, и немедленно закрываю - проблема исчезает. Итак, в моем случае Spring ждал сигнала закрытия потока. Хотя я использую автоматическое закрытие Java 8.Я хотел бы добавить что-то к предыдущим ответам, но поскольку у меня нет представителя для комментариев, я просто добавлю ответ. Это предназначено для пользователей Android, которые программируют на Java.
Согласно сообщению RollingBoy, этот код почти сработал для меня:
В моем случае waitFor () не запускался, потому что я выполнял инструкцию без возврата («ip adddr flush eth0»). Легкий способ исправить это - просто убедиться, что вы всегда что-то возвращаете в своем операторе. Для меня это означало выполнение следующего: «ip adddr flush eth0 && echo done». Вы можете читать буфер весь день, но если ничего не возвращается, ваш поток никогда не освободит свое ожидание.
Надеюсь, это кому-то поможет!
источник
process.waitFor()
что зависает, это то,reader.readLine()
что зависает, если у вас нет вывода. Я попытался использоватьwaitFor(long,TimeUnit)
тайм-аут, если что-то пойдет не так, и обнаружил, что это было чтение зависло. Из-за чего версия с ограниченным сроком действия требует другого потока для чтения ...Есть несколько возможностей:
stdout
.stderr
.stdin
.источник
Как уже упоминалось, вы должны использовать stderr и stdout .
По сравнению с другими ответами, начиная с Java 1.7, это еще проще. Вам больше не нужно создавать потоки самостоятельно, чтобы читать stderr и stdout .
Просто используйте
ProcessBuilder
и используйте методыredirectOutput
в сочетании сredirectError
илиredirectErrorStream
.источник
По той же причине вы также можете использовать
inheritIO()
для сопоставления консоли Java с внешней консолью приложения, например:источник
Вы должны попытаться использовать вывод и ошибку одновременно
источник
Думаю, я наблюдал аналогичную проблему: некоторые процессы запускались, казалось, успешно выполнялись, но не завершались. Функция waitFor () ждала вечно, если я не убил процесс в диспетчере задач.
Однако все работало хорошо в случаях, когда длина командной строки составляла 127 символов или меньше. Если длинные имена файлов неизбежны, вы можете использовать переменные среды, которые могут позволить вам сохранить короткую строку командной строки. Вы можете сгенерировать пакетный файл (используя FileWriter), в котором вы установите свои переменные среды перед вызовом программы, которую вы действительно хотите запустить. Содержимое такой партии может выглядеть так:
Последний шаг - запуск этого командного файла с использованием среды выполнения.
источник
Вот метод, который мне подходит. ПРИМЕЧАНИЕ. В этом методе есть код, который может не относиться к вам, поэтому попробуйте проигнорировать его. Например, «logStandardOut (...), git-bash и т. Д.».
}
источник
Асинхронное чтение потока в сочетании с отказом от ожидания с таймаутом решит проблему.
Вы можете найти страницу, объясняющую это здесь http://simplebasics.net/.net/process-waitforexit-with-a-timeout-will-not-be-able-to-collect-the-output-message/
источник