Java ProcessBuilder: внешний процесс зависает - PullRequest
2 голосов
/ 29 октября 2009

Я использую Java-класс ProcessBuilder для запуска внешнего процесса. Процесс не должен завершаться раньше, чем программа Java; он должен оставаться в живых в режиме команда / ответ.

Я знаю, что потоки процесса могут легко «застрять», если пренебречь, поэтому я сделал следующее: Программа считывает объединенные потоки вывода и ошибок процесса в потоке «считывателя» и использует поток «записывающего» для управления командами. Поток читателя блокирует чтение символов из выходных данных процесса, буферизует их в строки и отправляет результаты. Поток писателя записывает полные «командные» строки через PrintWriter; он использует очередь, чтобы гарантировать, что никакие две записи команд не «слишком близки» (в настоящее время 100 мс), и что никакая новая команда не записывается до завершения вывода предыдущей команды. Я также вызываю flush () и checkError () после каждого println ().

Эта схема отлично работает в течение нескольких секунд или минут, затем поток чтения зависает при блокировке чтения (). Никаких ошибок, никаких исключений, никаких выходных данных процесса. После этого ничто не оживит внешний процесс (кроме перезапуска). (Кстати, это происходит как в Linux, так и в Windows.)

Я рассмотрел код и контрольные примеры в Jakarta Commons Exec и в Plexus Utils http://plexus.codehaus.org/plexus-utils/, но (a) ни один из них не дает пример использования долгоживущего Процесса, а (b) ни делать что-то принципиально отличное от того, что я описал.

Кто-нибудь знает, что здесь происходит, пожалуйста? Спасибо!

Ответы [ 3 ]

1 голос
/ 07 декабря 2011

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

Я тестировал как в Windows / Linux с множеством встроенных приложений cmd / bash, так и в других двоичных файлах cmd, и он отлично работает, за исключением того, что в некоторых случаях он просто вызывает исключение потока Io, что я делаю, перехватывая исключение и перезапуск поток снова, так что программа продолжает работать.

Если вы пытаетесь, например, запустить ssh в Linux, то вы можете столкнуться с проблемой, например, из-за соображений безопасности, вы не сможете писать на тот же стандартный ввод.

Попробуйте взять входные данные из System.in и посмотреть, работает ли он, в моем случае это сработало

1 голос
/ 29 октября 2009

У вас также есть поток, управляющий stderr? Вы упоминаете только два потока.

0 голосов
/ 29 октября 2009

Просто предположение, но вы пытались объединить потоки ошибок и вывода?

...