Я использую ProcessBuilder
для запуска инструмента командной строки, который мы используем. Во время запуска инструмент задает два вопроса «да/нет», поэтому обычно я дважды отвечаю «y», а затем каждый раз нажимаю клавишу ввода. Моя проблема в том, что инструмент всегда заканчивает выполнение при запуске с cmd, но когда я запускаю его через свой Java-код, он иногда работает и иногда застревает на while ((n = op.read(buffer)) != -1)
(с тем же вводом).ProcessBuilder BufferedReader read() blocking
Вот мой код. Я делаю что-то неправильно? Что мне не хватает? Благодарю.
List<String> processArgs = new ArrayList<>();
processArgs.add(0, "java");
processArgs.add(1, "-jar");
processArgs.add(2, JAR_PATH);
processArgs.add(3, "-put");
processArgs.addAll(args);
try
{
// run tool with put
ProcessBuilder pb = new ProcessBuilder(processArgs);
pb.directory(new File("src\\temp"));
pb.redirectErrorStream(true);
Process p = pb.start();
// write 'y' to the tool's stdin.
String answer = "y" + System.getProperty("line.separator");
// yes to first question
p.getOutputStream().write(answer.getBytes());
p.getOutputStream().flush();
// read tool's process stdout
this.op = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringWriter sw = new StringWriter();
int n = 0;
boolean answered = false;
char[] buffer = new char[BUFFER_SIZE];
while ((n = op.read(buffer)) != -1)
{
sw.write(buffer, 0, n);
if (sw.toString().contains("second question") && !answered)
{
// yes to second question
p.getOutputStream().write(answer.getBytes());
p.getOutputStream().flush();
answered = true;
}
}
stdout = sw.toString();
exitCode = p.waitFor();
}
catch (IOException | InterruptedException e)
{
throw new ToolException("process had an exception:\n" + e.getMessage());
}
UPDATE: Я изменил код и добавил pb.redirectErrorStream(true)
, но теперь этот процесс еще будет заблокирован на op.read(buffer)
. Когда я отлаживаю, кажется, что он застрял во втором вопросе, хотя я дважды писал «y» в выходной поток. Использую ли я getOutputStream()
неправильно?
ВТОРОЕ ОБНОВЛЕНИЕ: Второй вопрос не получил второй «y» в качестве ответа, и это заставило процесс ждать ввода. Я изменил код, поэтому я покажу правильный способ вставки ввода в выходной поток subprocess.
Спасибо, много, Питер, это помогло, но я все равно заблокирован на read(). См. Мое обновление. – gamlieldor
@gamlieldor Я предлагаю вам распечатать вывод по мере его запуска. Скорее всего, нас ждет вход. –
Я сделал, и вы правы, он ждет ввода по второму вопросу. Как заставить его принимать «y» ответы один раз для первого вопроса и один раз для второго? Я попытался перенаправить вход pb в файл с «y», разделенным новыми строками, но это не помогло. – gamlieldor