Блокировка потока ошибок при запуске внешней команды с Java

1

Работая над SEAndroid, я вызываю команды Setools из своего Java-приложения. Он отлично работает с небольшой политикой SEAndroid, и теперь мне нужно проверить свой инструмент с помощью реальной политики SEAndroid. Но, к сожалению, у меня возникла проблема с потоком ошибок.

Здесь мой код, который я использовал для вызова внешних команд:

public static BufferedReader runCommand(final String[] args)
            throws IOException {

    BufferedReader stdInput = null;
    BufferedReader stdError = null;
    try {
        Process p = Runtime.getRuntime().exec(args);

        stdInput = new BufferedReader(new
                InputStreamReader(p.getInputStream()));

        stdError = new BufferedReader(new
                InputStreamReader(p.getErrorStream()));

        // read any errors from the attempted command
        String s = null;
        StringBuilder err = new StringBuilder();

        while ((s = stdError.readLine()) != null) {
            err.append(s + "\n");
        }
        if (err.length() != 0) {
            throw new IOException(err.toString());
        }

        return stdInput;
    } finally {
        if (stdError != null) {
            stdError.close();
        }
    }
}

Итак, как вы можете видеть, я вызываю внешнюю команду. Затем прочитайте поток ошибок и выбросите исключение, если есть какие-либо ошибки, в противном случае я возвращаю InputStream, поэтому я смогу его проанализировать позже.

С реальной политикой SEAndroid поток ошибок, кажется, блокируется (даже если я читаю один символ), и я не могу разобрать результат команды. Если я закрою поток ошибок, не прочитав ничего, приложение работает нормально, но я хочу обрабатывать ошибки, если они есть. Если я наберу команду в консоли, она отлично работает.

В первом случае (с малой политикой SEAndroid) вывод команды мал (~ 350 строк). Во втором случае (с реальной политикой SEAndroid) вывод команды больше (> 1500 строк).

Возможно ли, что размер выходного потока влияет на поток ошибок? Эти два потока являются двумя отличительными ресурсами, не так ли? Тот факт, что я не читаю выходной поток, сразу имеет значение?

Я боюсь, что это не проблема программирования, а проблема системы...

Любое предложение?

Заранее спасибо за вашу помощь =)

Редактировать:

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

Теги:
stream
runtime.exec

2 ответа

1
Лучший ответ

Во-первых, вероятно, лучше использовать новый класс ProcessBuilder, а не Runtime exec. Если вы хотите сделать еще один шаг, вы даже можете использовать Apache commons-exec, который заботится о потоковой обработке и других вещах для вас.

Далее, как вы обнаружили, управление процессом является сложной задачей на Java, и вы столкнулись с одной из ее сложных проблем. Из документации для java Класс процесса:

Родительский процесс использует эти потоки для подачи ввода и получения вывода из подпроцесса. Поскольку некоторые собственные платформы обеспечивают ограниченный размер буфера для стандартных потоков ввода и вывода, неспособность оперативно записать входной поток или прочитать выходной поток подпроцесса, может привести к блокировке подпроцесса и даже к взаимоблокировке.

У вас должно быть что-то, потребляющее потоки (Error and Output), или вы рискуете затормозить - каждый из них должен быть прочитан в своих потоках. Использование чего-то вроде StreamGobbler (google it, есть много там) было бы хорошим шагом, или вы можете катиться самостоятельно, если вы так склонны. Не так уж сложно правильно понять, но если вы не знакомы с многопоточным процессом, вы можете захотеть взглянуть на реализацию какого-либо другого пользователя или перейти по пути Apocal commons-exec.

  • 0
    Благодарю. Я использую processBuilder с StreamGobbler, и он работает. Мне даже не нужно ничего менять в моем приложении. Я использовал код, который нашел здесь . У вас есть хорошая реализация StreamGobbler, чтобы предложить?
  • 0
    Я считаю, что когда я боролся с этой же проблемой, я использовал тот же код для моего шаблона. Я немного изменил его, чтобы удовлетворить свои потребности, но основная структура была той же.
Показать ещё 1 комментарий
0

Обработка вывода настолько раздражает, что я написал небольшую библиотеку под названием jproc, которая занимается проблемой потребления stdout и stderr. Он может просто фильтровать строки через внешние программы, это нравится:

ProcBuilder.filter("x y z","sed" ,"s/y/a/")

Он также позволяет указать тайм-аут для завершения и конвертировать ненулевые коды выхода в исключение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню