Лучший способ запустить внешний процесс из веб-сервиса Java? - PullRequest
2 голосов
/ 13 марта 2009

Я унаследовал кодовую базу веб-сервисов Java (BEA / Oracle Weblogic) и мне нужно запустить / запустить внешнее фоновое приложение из веб-сервиса.

Я уже пробовал:

ProcessBuilder pb = new ProcessBuilder(arg);
pb.start();

а также:

Runtime.exec(cmdString);

Но при запуске приложений подобным образом наблюдается странное поведение (т. Е. Запущенное приложение перестает работать, даже если процесс все еще активен. - Приложение работает нормально при запуске вручную из обычной командной строки).

Есть ли лучший способ запуска внешних процессов?

РЕДАКТИРОВАТЬ: ----------------------

У меня есть дополнительная информация, которая может пролить свет на проблему.

  • Процесс, который мы пытаемся запустить, потребует нескольких часов, поэтому ожидание завершения (с помощью waitfor()) в веб-сервисе не будет идеальным сценарием.
  • Да, процесс, который мы пытаемся запустить с веб-сервиса, был создан одним из членов команды [кий: ваши глаза закатились ... сейчас]

У меня был успех , когда я использовал компоновщик процессов для запуска bash-скрипта, когда внешнее приложение запускалось как фоновый процесс (с использованием «&»).

#!/bin/bash
java -jar myApp.jar &

Это, очевидно, создает потерянный процесс, но по крайней мере приложение продолжает выполняться.

Ответы [ 5 ]

2 голосов
/ 18 марта 2009

Проще говоря: если запущенное приложение пишет в SDTOUT / STDIN, и вы не часто их сбрасываете (см. Process.getErrorStream / Process.getInputStream), тогда процесс будет блокироваться, когда буфер заполнен (это действительно мало, 4 КБ или меньше).

Я рекомендую вам вызвать ProcessBuilder.redirectErrorStream () перед началом процесса. Затем, после этого, создайте поток с методом run () в соответствии с:

public void run() {
    BufferedReader reader = 
        new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}
2 голосов
/ 14 марта 2009

By "перестает работать, даже если процесс все еще активен" Я предполагаю, что вы могли ожидать некоторого вывода от запущенного вами приложения и ничего не получать.

Попробуйте использовать следующее:

ProcessBuilder pb = new ProcessBuilder(arg);
Process p = pb.start();
p.waitFor();

waitFor () заставляет текущий поток ждать, если необходимо, до тех пор, пока процесс, представленный этим объектом Process, не завершится.

http://java.sun.com/javase/6/docs/api/java/lang/Process.html#waitFor()

2 голосов
/ 14 марта 2009

Во-первых, это происходит в Windows или в Linux? Кроме того, что запускаемое приложение должно более или менее делать? (это скрипт? это двоичный файл? ваш двоичный файл?)

EDIT

ОК, поэтому запуск сценария bash (с использованием ProcessBuilder), который в свою очередь порождает новую JVM (java -jar myApp.jar), работает.

Что именно происходит, когда вы пытаетесь создать новую JVM напрямую с использованием ProcessBuilder? Вы изначально сказали:

перестало работать запущенное приложение

  1. Под запущенным приложением вы подразумеваете "java -jar myApp.jar", при прямом вызове не через промежуточный bash скрипт?
  2. Какие точные и полные параметры (и их значения) вы передаете различным ProcessBuilder методам (и в каком порядке), когда вы пытаетесь запустить Java напрямую, и эта новая JVM перестает работать? (например, предоставить аннотированный код)
  3. Если вы устанавливаете lsof на вашем * nix-компьютере, какой файл будет показан как связанный с дескриптором файла 2 (см. Столбец FD) при запуске: lsof -p 1234 (где 1234 - идентификатор процесса "зависшей" JVM?) Может быть интересно прикрепить сюда весь вывод команды lsof.
  4. Что добавляется к файлу, который вы определили на шаге 3 выше (для файлового дескриптора 2), до нескольких секунд после ввода команды: kill -QUIT 1234 (где 1234 - идентификатор процесса «зависшего») JVM?)
1 голос
/ 14 марта 2009

Правильно ли вы обрабатываете стандартный ввод и вывод процесса? Если стандартный ввод или вывод обрабатывается вашим приложением, а вы не обрабатываете его должным образом, то выполняемый вами процесс будет зависать в ожидании ввода-вывода.

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

0 голосов
/ 13 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...