2011-01-12 1 views
1

Когда я выполнить команду в отдельном процессе, например, с помощью Runtime.getRuntime().exec(...) метода, чье JavaDoc состояния:Что делать с ненужными потоками из внешнего процесса?

Executes the specified command and arguments in a separate process. 

Что мне нужно делать с потоками из этого процесса, зная, что этот процесс будет жить пока не существует Java-программа? (это деталь, но программа Java заботится об убийстве этого процесса, и сам процесс имеет встроенную защиту, где он убивает себя, если он заметит, что программа Java, которая породила его, больше не работает).

Если мы считаем, что этот процесс не производит никакого вывода (например, поскольку все сообщения об ошибках и stdout перенаправляются на/dev/null, и все коммуникации выполняются с использованием файлов/сокетов/что-то еще), что мне нужно сделать с входным потоком?

Должен ли я иметь один (или два?) Java-потока, запущенные ни для чего, пытаясь прочитать stdout/stderr?

Каков правильный способ справиться с долговременным внешним процессом, порожденным программой Java, которая вообще не создает stdout/stderr?

EDIT

В основном я обернуть скрипт в другом скрипте, который гарантирует, чтобы перенаправить все в /разработчика/нулевые. Я уверен, что мой Un * x будет несовместимым, если мой сценарий оболочки «outter» (тот, который перенаправляет все на/dev/null), все равно будет генерировать что-либо на stdout или stderr. Тем не менее, я нахожу, что это разумно, что я бы как-то предположил, что потоки выполняются в течение жизненного цикла приложения «ни для чего». На самом деле поражает ум.

ответ

1

Если все, как вы говорите, то вы, вероятно, можете их игнорировать.

Однако, редко все происходит так чисто. Возможно, в конечном итоге стоит создать единственный поток для вытаскивания stdout/stderr на всякий случай. В один прекрасный день он терпит неудачу и на самом деле что-то выдает, это тот день, когда вам нужно было знать, что получилось. 1 или 2 потока (я думаю, что это может быть сделано только с одним) не будут большими накладными расходами. Особенно, если вы правы, и из этих потоков ничего не выходит.

+0

Интересно. Я отредактирую свой вопрос ... В основном я завершаю скрипт оболочки в другом сценарии оболочки, который обязательно перенаправляет все на */dev/null *. Я уверен, что мой Un * x будет несовместимым, если мой сценарий оболочки «outter» (тот, который перенаправляет все на */dev/null *), все равно будет генерировать что-либо на * stdout * или * stderr *. – SyntaxT3rr0r

+0

@ SyntaxT3rr0r - Я понимаю. Я всего лишь один из тех параноидных людей. :) Я согласен, что дополнительные потоки, вероятно, не нужны. – rfeak

1

Я считаю, что правильный способ обработки ввода и вывода процесса, если вы не заинтересованы в них, - это быстро закрыть их. Если впоследствии дочерний процесс попытался вызвать чтение или запись на stdin или stdout, то будет выбрано исключение IOException. Ответственность за то, что он не может читать и писать, не несет ответственности за процесс ребенка.

Большинство процессов игнорируют тот факт, что они не могут писать и молча отбрасывать и записывать. Это справедливо в Java, где System.out является PrintWriter, поэтому любые IOExceptions, заданные stdout, игнорируются. Это в значительной степени то, что происходит, когда вы перенаправляете вывод на/dev/null - все выходные данные отбрасываются молча.

Похоже, вы прочитали API для процессов и почему важно читать/писать в процесс, если он ожидает, что он будет писать или читать самостоятельно. Но я повторю, проблема заключается в том, что некоторые ОС просто выделяют очень ограниченные буферы для (в частности) stdout, поэтому важно либо не допускать заполнения буферов. Это означает либо быстрое чтение любого выходного файла дочернего процесса, либо уведомление ОС, что вы не требуете вывода процесса, и что он может освободить все сохраненные ресурсы, и отклонить любую дальнейшую попытку записать в stdout или прочитать из stdin (скорее чем просто зависание, пока не станут доступны ресурсы).

+0

спасибо за ответ ... Я не просто прочитал его. Это то, что я прочитал его и что я постоянно укушен в b **** при запуске внешних процессов с Java на протяжении многих лет. Итак, теперь я принимаю весьма радикальный подход. На самом деле я просто подумал о чем-то другом: мой сценарий «outter» делает «nohup», создавая себе другой скрипт, не зависящий от hangups/kill и чьи потоки не имеют ** ничего ** с Java. Следовательно, из Java я могу прочитать/закрыть/уничтожить скрипт «outter» через некоторое время, зная, что внутренний скрипт будет невидимым для Java :) – SyntaxT3rr0r

+0

Детский процесс не обязательно является виртуальной машиной Java, поэтому он не может обязательно вызывать 'IOException' , Например, он может получить 'SIGPIPE' – finnw

+0

@finnw. Я не уверен, какова ваша точка. JVM получит тот же SIGPIPE и выбросит исключение IOException, когда оно его получит. Что делает процесс, когда он получает SIGPIPE, зависит от него. Я считаю, что программы, такие как grep, выйдут, если он получит SIGPIPE, но firefox или vlc все равно. – Dunes

Смежные вопросы