запуск удаленного (SSH) Java-приложения со сценарием оболочки не вернет локальное приглашение - PullRequest
0 голосов
/ 27 июня 2018

Я видел похожие вопросы, все решенные проблемы уже решены / не применимы.

У меня есть скрипт bash на удаленной машине, который запускает приложение Java. Соответствующие строки будут:

#!/usr/bin/env bash
...
java -cp /full/path/to/my.jar com.whatever.hi.wassup.MainClassThing \
    --arg-1 /full/path/to/relevant_dir --arg-2 /full/path/to/another_dir &
...
echo started my app
exit 0

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

На локальной машине я пытаюсь вызвать удаленный скрипт внутри локального bash-скрипта следующим образом:

#!/usr/bin/env bash
...
ssh remote_host myRemoteScript

Все мои тесты и другое Java-приложение возвращают локальное приглашение. Проблема в том, что это, однако, действительно запускает удаленное Java-приложение и идет до последней строки, выводя «запустил мое приложение», но скрипт останавливается, у меня нет локальной подсказки, если только я не Ctrl+C.

Используя ssh -v в рабочем приложении Java, я получаю это:

debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 2992, received 7060 bytes, in 24.4 seconds
Bytes per second: sent 122.6, received 289.2
debug1: Exit status 0

Еще в нерабочем приложении я получаю это:

debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
"started my app"

Но нет локальной подсказки. Я попытался запустить одну и ту же команду с nohup и disown, те же результаты. Как видно, команда имеет & в конце. Комментирование только этой строки в удаленном скрипте работает без проблем (и ничего не делает полезного), поэтому я предполагаю, что это как-то связано с самим приложением Java - но разве управление процессом не доходит до оболочки? Запуск myRemoteScript на удаленном компьютере также работает должным образом.

Это логин без пароля. Обе машины RHEL 7.2.

EDIT

Также пробовал:

  • ssh remote_host "myRemoteScript"
  • ssh -T remote_host myRemoteScript
  • ssh remote_host "bash -c myRemoteScript"
  • ssh remote_host "myRemoteScript; exit"

1 Ответ

0 голосов
/ 28 июня 2018

Вы можете перенаправить стандартный ввод, вывод и ошибку для процесса Java, чтобы его стандартный ввод, вывод и ошибка не были подключены к удаленному SSH-серверу:

java ... < /dev/null > /dev/null 2>&1 &

Это должно позволить удаленному серверу немедленно прекратить сеанс SSH.

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

Процесс Java, запущенный вашей удаленной командой, наследует каналы к серверу SSH в качестве стандартного ввода и т. Д. Сервер SSH не получает индикацию EOF на этих каналах, потому что все еще существует процесс с доступом к каналам.

Вы можете проверить это, выполнив команду наподобие:

ssh localhost 'sleep 10 < /dev/null > /dev/null &'

Если ssh завершает работу сразу, не дожидаясь завершения sleep, это означает, что вы получили удаленный SSH-сервер, который не ждет в спящем режиме.

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

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