Tratar:
#!/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"
Normalmente, bash
ignorará cualquier señal mientras se ejecuta un proceso secundario. Al iniciar el servidor, se &
colocará en segundo plano en el sistema de control de trabajo del shell, con la $!
retención del PID del servidor (para ser utilizado con wait
y kill
). Las llamadas wait
esperarán a que finalice el trabajo con el PID especificado (el servidor) o que se activen las señales .
Cuando el shell recibe SIGTERM
(o el servidor sale independientemente), la wait
llamada regresará (saliendo con el código de salida del servidor, o con el número de señal + 128 en caso de que se reciba una señal). Luego, si el shell recibió SIGTERM, llamará a la _term
función especificada como el controlador de trampa SIGTERM antes de salir (en el que hacemos cualquier limpieza y propagamos manualmente la señal al proceso del servidor usando kill
).
wait
se necesita la llamada posterior.exec /bin/start/main/server --nodaemon
(en cuyo caso el proceso de shell se reemplaza con el proceso del servidor y no necesita propagar ninguna señal) o lo usa/bin/start/main/server --nodaemon &
, peroexec
no es realmente significativo._term()
función debería hacerlowait "$child"
nuevamente. Esto puede ser necesario si tiene algún otro proceso de supervisión esperando que el script de shell muera antes de reiniciarlo nuevamente, o si también está atrapadoEXIT
para hacer una limpieza y necesita que se ejecute solo después de que el proceso secundario haya finalizado.exec
o quieres establecer trampas .Bash no reenvía señales como SIGTERM a los procesos que está esperando actualmente. Si desea finalizar su secuencia de comandos siguiendo su servidor (permitiéndole manejar señales y cualquier otra cosa, como si hubiera iniciado el servidor directamente), debe usar
exec
, que reemplazará el shell con el proceso que se está abriendo :Si usted necesita para mantener la cáscara alrededor por alguna razón (es decir. Que tiene que hacer algo de limpieza después de que el servidor termina), se debe utilizar una combinación de
trap
,wait
ykill
. Ver la respuesta de SensorSmith .fuente
Andreas Veithen señala que si no necesita regresar de la llamada (como en el ejemplo del OP), simplemente llamar a través del
exec
comando es suficiente ( respuesta de @Stuart P. Bentley ). De lo contrario, el "tradicional"trap 'kill $CHILDPID' TERM
(la respuesta de @ cuonglm) es un comienzo, pero lawait
llamada en realidad regresa después de que se ejecuta el controlador de trampa, que puede ser aún antes de que el proceso secundario salga. Por lo tanto,wait
se recomienda una llamada "extra" a ( respuesta de @ user1463361 ).Si bien esto es una mejora, todavía tiene una condición de carrera, lo que significa que el proceso nunca puede salir (a menos que el señalizador vuelva a intentar enviar la señal TERM). La ventana de vulnerabilidad es entre registrar el controlador de trampa y registrar el PID del niño.
Lo siguiente elimina esa vulnerabilidad (empaquetada en funciones para su reutilización).
fuente
La solución proporcionada no funciona para mí porque el proceso finalizó antes de que el comando de espera realmente terminara. Encontré que el artículo http://veithen.github.io/2014/11/16/sigterm-propagation.html , el último fragmento funciona bien en mi caso de aplicación, comenzó en OpenShift con sh runner personalizado. Se requiere el script sh porque necesito tener la capacidad de obtener volcados de subprocesos, lo que es imposible en caso de que el PID del proceso Java sea 1.
fuente