Essayer:
#!/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"
Normalement, bash
ignorera tous les signaux pendant l'exécution d'un processus enfant. Le démarrage du serveur avec &
sera intégré au système de contrôle des tâches du shell, en $!
tenant le PID du serveur (à utiliser avec wait
et kill
). L'appel wait
attendra ensuite que le travail avec le PID spécifié (le serveur) soit terminé ou que tous les signaux soient déclenchés .
Lorsque le shell reçoit SIGTERM
(ou le serveur quitte indépendamment), l' wait
appel est renvoyé (avec le code de sortie du serveur ou le numéro de signal + 128 en cas de réception d'un signal). Par la suite, si le shell a reçu SIGTERM, il appellera la _term
fonction spécifiée en tant que gestionnaire d’interruptions SIGTERM avant de quitter (dans lequel nous effectuons tout nettoyage et propagons manuellement le signal au processus serveur à l’aide de kill
).
wait
appel suivant est alors nécessaire?exec /bin/start/main/server --nodaemon
(dans ce cas, le processus shell est remplacé par le processus serveur et vous n’avez pas besoin de propager de signaux), soit vous utilisez/bin/start/main/server --nodaemon &
, mais celaexec
n’a pas vraiment de sens._term()
vous devriez le faire àwait "$child"
nouveau dans la fonction . Cela peut être nécessaire si un autre processus de supervision attend la fin du script shell avant de le redémarrer à nouveau, ou si vous êtes également bloquéEXIT
pour effectuer un nettoyage et si vous souhaitez qu'il s'exécute uniquement une fois le processus enfant terminé.exec
ou vous voulez installer des pièges .Bash ne transmet pas de signaux tels que SIGTERM aux processus qu’il attend actuellement. Si vous voulez terminer votre script en vous connectant à votre serveur (en lui permettant de gérer les signaux et tout le reste, comme si vous aviez démarré le serveur directement), vous devriez utiliser
exec
, qui remplacera le shell par le processus en cours d'ouverture :Si vous avez besoin de garder la coquille autour pour une raison quelconque ( par exemple. Vous devez faire un nettoyage après que le serveur se termine), vous devez utiliser une combinaison de
trap
,wait
etkill
. Voir la réponse de SensorSmith .la source
Andreas Veithen souligne que si vous n'avez pas besoin de revenir de l'appel (comme dans l'exemple du PO), un simple appel à l'aide de la
exec
commande suffit ( réponse de @Stuart P. Bentley ). Sinon, le "traditionnel"trap 'kill $CHILDPID' TERM
(réponse de @ cuonglm) est un début, mais l'wait
appel revient en réalité après l'exécution du gestionnaire d'interruptions, ce qui peut être encore avant la fin du processus enfant. Ilwait
est donc conseillé de faire un "extra" appel ( réponse de @ user1463361 ).Bien qu'il s'agisse d'une amélioration, il existe toujours une condition de concurrence critique, ce qui signifie que le processus ne peut jamais se terminer (à moins que le signaleur ne tente d'envoyer le signal TERM). La fenêtre de vulnérabilité se situe entre l'enregistrement du gestionnaire d'interruptions et l'enregistrement du PID de l'enfant.
Ce qui suit élimine cette vulnérabilité (intégrée dans des fonctions pour la réutilisation).
la source
La solution fournie ne fonctionne pas pour moi car le processus a été tué avant la fin de la commande d'attente. J'ai trouvé cet article http://veithen.github.io/2014/11/16/sigterm-propagation.html , le dernier extrait qui fonctionne bien dans mon cas d'application démarrée dans OpenShift avec un coureur personnalisé. Le script sh est requis car je dois avoir la capacité d'obtenir des vidages de threads, ce qui est impossible dans le cas où le processus PID du processus Java est à 1.
la source