SSHJ навсегда зависает на join()

Я выполняю некоторые команды, используя SSHJ, я делаю это с помощью этого метода:

  private Command executeCommand(String command, SSHClient client) {
    Command commandObject = client.startSession().exec(command);
    commandObject.join();
    return commandObject;
  }

Он работает хорошо, пока я не выполню эту команду:

cd $SOLR; nohup java -Dsolr.solr.home=./solr -DSTOP.PORT=8079 -DSTOP.KEY=stopkey -jar start.jar 2> logs/solr.log &

В этом случае вся программа зависает

commandObject.join();

Конечно, процесс, который он запускает, запущен. Также сразу же возвращается та же строка, выполненная из оболочки.

Любая идея, почему и как это преодолеть?

РЕДАКТИРОВАТЬ: то же самое происходит, когда я не присоединяюсь к(), а читаю sysout команды (с commons-io):

IOUtils.toString(commandObject.getInputStream()))

person ilfrin    schedule 23.02.2012    source источник
comment
Одной из идей может быть перенаправление stdin и stderr, поэтому может помочь размещение 2>&1 перед последним амперсандом. Хотя у меня аналогичная проблема с другой командой, так что, вероятно, это не решит ее полностью.   -  person bstempi    schedule 24.01.2014
comment
Исправление к моему комментарию: это бесполезно - nohup перенаправит вас, если вы не укажете иначе. Я заметил, что в этой библиотеке есть некоторые проблемы с потоками; возможно, вы сталкивались с одним?   -  person bstempi    schedule 24.01.2014
comment
@ilfrin, основной поток блокируется, потому что вы вызываете commandObject.join() без тайм-аута. Это блокирует текущий поток для ожидания уведомления. Если вызываемая программа зависает, основной поток также зависает.   -  person Boyan    schedule 16.02.2016


Ответы (2)


Предположительно, приложение Java, которое вы используете, является демоном? (или, по крайней мере, он долго ждет перед выходом)

Возможно, будет лучше иметь на целевой машине специальный скрипт, который управляет инициализацией/завершением работы демона, а не полагаться на SSH-клиентов для отправки правильной последовательности команд. Таким образом, сценарий инкапсулирует все, что необходимо для чистого запуска и остановки вашего демона и других приложений, которым необходимо управлять им, просто вызывая этот сценарий для запуска и остановки без необходимости знать подробности о том, где вести журнал, для его запуска требуется команда java. , как фонировать процесс и т.д.

Вы можете создать свой собственный скрипт в стиле инициализации или использовать Java Service Wrapper от Tanuki (или аналогичный) для этого.

person Jonny    schedule 21.08.2012

У меня была такая же проблема.

Моя личная рекомендация заключается в том, что всякий раз, когда вы используете join, вы должны установить некоторый тайм-аут для истечения срока его действия и не блокировать поток навсегда. В моем случае для использования нескольких команд я инициализирую экземпляр Shell и, например, сделаю что-то вроде этого:

try
{
            shell = session.startShell();
}
catch (Exception e)
{
            // failed to open
            return;
}
outputStream = shell.getOutputStream();
outputStream.write(Strings.toUTF8ByteArray("some fast command\n"));
outputStream.flush();
try {   shell.join(1, TimeUnit.SECONDS); }
catch (Exception e) {}
outputStream.write(Strings.toUTF8ByteArray("some complex command\n"));
outputStream.flush();
try {   shell.join(30, TimeUnit.SECONDS); }
catch (Exception e) {}

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

person Fernando Martín Besteiro    schedule 15.03.2016