#java #shell #exec #apache-commons-exec
#java #оболочка #exec #apache-commons-exec
Вопрос:
Я пытаюсь запустить некоторые сценарии оболочки для Java с помощью пакета commons exec и очистить буферы STDOUT amp; STDERR с помощью PumpStreamHandler. Большинство сценариев выполняются нормально, без каких-либо проблем, но некоторые из них зависают.
Особенно тех сценариев, для возврата которых требуется некоторое время. Я предполагаю, что PumpStramHandle может считывать конец потока, поскольку некоторое время в поток ничего не помещается, и после этого буферы заполняются.
Есть ли лучший способ решить эту проблему?
Ответ №1:
Извлеките выполняемый скрипт / команду и запустите его самостоятельно в командной оболочке. При запуске вещей, которые ‘выполняются’ на каком-либо другом языке (c, c , python java и т.д.), И все начинает идти ‘неправильно’, это должно быть первым шагом.
Вы обнаруживаете, что происходят всевозможные вещи. Сценарии, которые останавливаются и запрашивают ввод (большой источник зависаний), ошибки, которые неправильно анализируются, ошибки seg, файлы не найдены.
Комментарии:
1. Я признаю, что вы правы. Но в данном случае это действительно не вариант.
Ответ №2:
Чтобы расширить первый ответ о непосредственном запуске команд для тестирования, вы можете проверить свою гипотезу с помощью простого скрипта, который некоторое время отключается, прежде чем вернуть выходные данные. Если вы не можете протестировать свою команду, протестируйте свою идею.
#!/bin/bash
sleep 60;
echo "if you are patient, here is your response"
Ответ №3:
Не лучшее решение. Но делает то, что мне нужно. 🙂
class OSCommandLogger extends Thread {
private static final Logger logger = Logger.getLogger(OSCommandLogger.class);
private volatile boolean done = false;
private final String name;
// Each process is associated with an error and output stream
private final BufferedReader outputReader;
private final BufferedReader errorReader;
private final Logger log;
/**
* Reads the output amp; error streams of the processes and writes them to
* specified log
*
* @param p
* @param name
* @param log
*/
OSCommandLogger(Process p, String name, Logger log) {
// Create readers
outputReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
errorReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
this.log = log;
if (name != null)
this.name = name;
else
this.name = "OSCommandStreamsLogger";
}
private void logLine(BufferedReader reader, boolean isError) {
try {
String line = null;
while ((line = reader.readLine()) != null) {
if (log != null amp;amp; log.isDebugEnabled()) {
if (!isError)
log.debug("[OuputStream] " line);
else
log.warn("[ErrorStream] " line);
} else
logger.debug(line);
}
} catch (Exception ex) {
if (log != null)
log.error(name ":" "Error while reading command process stream", ex);
}
}
public void run() {
while (!done) {
logLine(outputReader, false);
logLine(errorReader, true);
try {
// Sleep for a while before reading the next lines
Thread.sleep(100);
} catch (InterruptedException e) {
log.debug("Done with command");
}
}
// Process is done. Close all the streams
try {
logLine(outputReader, false);
outputReader.close();
logLine(errorReader, true);
errorReader.close();
if (log != null amp;amp; log.isDebugEnabled())
log.debug(name ": Closed output/ error Streams.");
} catch (IOException ie) {
if (log != null)
log.error(name ":" "Error while reading command process stream", ie);
}
}
public void stopLoggers() {
if (log != null amp;amp; log.isDebugEnabled())
log.debug(name ":Stop loggers");
this.done = true;
}
}
Использование:
Process p = Runtime.getRuntime().exec("Command");
OSCommandLogger logger = new OSCommandLogger(p, "Command", log);
// Start the thread using thread pool
threadExec.executeRunnable(logger);
int exitValue = p.waitFor(); // Wait till the process is finished
// Required to stop the logger threads
logger.stopLoggers();
logger.interrupt();