Ну, во-первых, давайте напишем тестовый скрипт, который проверяет то, что вы видите:
$ cat /tmp/test.sh
#!/bin/bash
for sig in SIGINT SIGTERM SIGHUP; do
trap "echo Caught $sig" $sig
done
echo Traps registered, sleeping
sleep 10
echo Done sleeping, exiting
Когда я вызываю это через:
new ProcessBuilder("/tmp/test.sh").inheritIO().start().waitFor(1, TimeUnit.SECONDS);
Я вижу процесс Javaзавершается через 1 секунду (после истечения времени ожидания waitFor()
), но подпроцесс продолжает работать (сообщение Done sleeping
выводится на консоль после выхода из JVM).Это согласуется с тем, что обсуждалось в этом вопросе .
Итак, первое, что я бы предложил сделать, это проверить ваше первоначальное предположение о том, что подпроцесс фактически уничтожен;возможно, что-то еще идет не так, что заставляет его умереть по другой причине.Использование .inheritIO()
может помочь в отладке, если подпроцесс генерирует сообщения об ошибках, которых вы не видите.
Все это говорит о том, что nohup
может быть не тем, что вы хотите, а 'этим другим парнем' заметки;nohup
только заставляет процесс игнорировать SIGHUP
, и он все равно будет учитывать другие сигналы, в частности SIGINT
и SIGTERM
(Process.destroy()
отправляет, например, SIGTERM
).См. этот вопрос для получения дополнительной информации.
Как и во всех проблемах в программировании, введение большего количества слоев, вероятно, поможет:)
Создайте сценарий оболочки, который обрабатывает желаемую логику отвержения,например,
$ cat start-and-disconnect.sh
#!/bin/bash
# obviously tweak this as necessary to get the behavior you want,
# such as redirecting output or using disown instead of nohup
nohup "$@" &
Преимущество здесь в том, что Bash (или любая оболочка, которую вы предпочитаете) имеет лучшее управление процессами, чем Java, и теперь вы можете тестировать его изолированно, без необходимости компилировать и запускать приложение Java..
Когда вы довольны сценарием, ваш код Java просто становится:
new ProcessBuilder("/path/to/start-and-disconnect.sh", "/path/to/your_binary.sh")
.inheritIO().start().waitFor();
Вы можете безопасно .waitFor()
завершить вызов, так как start-and-disconnect.sh
завершится после запускаего подпроцесс.