Пытаться:
#!/bin/bash
_term() {
echo "Caught SIGTERM signal!"
kill -TERM "$child" 2>/dev/null
}
trap _term SIGTERM
echo "Doing some initial work...";
/bin/start/main/server --nodaemon &
child=$!
wait "$child"
Обычно bash
игнорирует любые сигналы во время выполнения дочернего процесса. Запуск сервера с помощью &
фонового перехода в систему управления заданиями оболочки с $!
удержанием PID сервера (для использования с wait
и kill
). wait
После этого вызов будет ожидать завершения задания с указанным PID (сервером) или запуска любых сигналов .
Когда оболочка получает SIGTERM
(или сервер выходит независимо), wait
вызов возвращается (выход с кодом выхода сервера или с номером сигнала + 128 в случае, если сигнал был получен). После этого, если оболочка получила SIGTERM, она будет вызывать _term
функцию, указанную в качестве обработчика прерываний SIGTERM перед выходом (в котором мы выполняем любую очистку и вручную распространяем сигнал на серверный процесс, используя kill
).
wait
тогда нужен последующий вызов?exec /bin/start/main/server --nodaemon
(в этом случае процесс оболочки заменяется серверным процессом, и вам не нужно распространять какие-либо сигналы), либо вы используете/bin/start/main/server --nodaemon &
, ноexec
это не имеет особого смысла._term()
функции вы должныwait "$child"
снова. Это может быть необходимо, если у вас есть какой-то другой надзорный процесс, ожидающий смерти сценария оболочки, прежде чем снова его перезапускать, или если вы также оказалисьEXIT
в ловушке, чтобы выполнить некоторую очистку и нуждаетесь в его запуске только после завершения дочернего процесса.exec
, либо вы хотите установить ловушки .Bash не передает сигналы, подобные SIGTERM, процессам, которые он в данный момент ожидает. Если вы хотите завершить ваш скрипт, перейдя на ваш сервер (позволяя ему обрабатывать сигналы и все остальное, как если бы вы запустили сервер напрямую), вы должны использовать
exec
, который заменит оболочку с открытым процессом :Если вам нужно сохранить оболочку вокруг какой - то причины (то есть. Вы должны сделать некоторые очистки после завершает сервер), вы должны использовать комбинацию
trap
,wait
иkill
. Смотрите ответ SensorSmith .источник
Андреас Вайтен отмечает, что если вам не нужно возвращаться из вызова (как в примере с OP), достаточно просто вызвать
exec
команду ( ответ @Stuart P. Bentley ). В противном случае «традиционный»trap 'kill $CHILDPID' TERM
(ответ @ cuonglm) является началом, ноwait
вызов фактически возвращается после выполнения обработчика прерываний, который может быть еще до фактического завершения дочернего процесса. Поэтомуwait
рекомендуется «дополнительный» вызов ( ответ @ user1463361 ).Несмотря на то, что это улучшение, у него все еще есть состояние гонки, что означает, что процесс может никогда не завершиться (если сигнализатор не попытается отправить сигнал TERM). Окно уязвимости находится между регистрацией обработчика ловушек и записью PID ребенка.
Следующее устраняет эту уязвимость (упаковано в функции для повторного использования).
источник
Предоставленное решение не работает для меня, потому что процесс был убит до того, как команда ожидания фактически закончилась. Я обнаружил, что в статье http://veithen.github.io/2014/11/16/sigterm-propagation.html последний фрагмент хорошо работает в моем случае приложения, запущенного в OpenShift с настраиваемым sh runner. Скрипт sh необходим, потому что мне нужна возможность получать дампы потоков, что невозможно в случае, если PID процесса Java равен 1.
источник