Próbować:
#!/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"
Zwykle bash
ignoruje wszelkie sygnały podczas wykonywania procesu potomnego. Uruchomienie serwera &
spowoduje umieszczenie go w tle w systemie kontroli zadań powłoki, z $!
zachowaniem PID serwera (do użycia z wait
i kill
). Wywołanie wait
będzie wtedy czekać na zakończenie zadania z określonym PID (serwerem) lub na wyzwolenie sygnałów .
Gdy powłoka odbierze SIGTERM
(lub serwer wyjdzie niezależnie), wait
połączenie zostanie zwrócone (wyjście z kodem wyjścia serwera lub z numerem sygnału + 128 w przypadku odebrania sygnału). Następnie, jeśli powłoka otrzymała SIGTERM, wywoła _term
funkcję określoną jako moduł obsługi pułapki SIGTERM przed wyjściem (w którym przeprowadzamy czyszczenie i ręcznie propagujemy sygnał do procesu serwera za pomocą kill
).
wait
wywołanie jest potrzebne?exec /bin/start/main/server --nodaemon
(w takim przypadku proces powłoki jest zastępowany procesem serwera i nie musisz propagować żadnych sygnałów), albo używasz/bin/start/main/server --nodaemon &
, ale wtedyexec
nie ma to naprawdę znaczenia._term()
funkcji powinieneśwait "$child"
ponownie. Może to być konieczne, jeśli jakiś inny proces nadzorujący czeka na śmierć skryptu powłoki przed ponownym uruchomieniem go ponownie, lub jeśli zostałeś uwięziony wEXIT
celu wykonania czyszczenia i konieczne jest uruchomienie go dopiero po zakończeniu procesu potomnego.exec
, albo chcesz ustawić pułapki .Bash nie przekazuje sygnałów takich jak SIGTERM do procesów, na które obecnie czeka. Jeśli chcesz zakończyć swój skrypt, dzieląc się na serwer (pozwalając mu obsługiwać sygnały i cokolwiek innego, tak jakbyś uruchomił serwer bezpośrednio), powinieneś użyć
exec
, który zastąpi powłokę z otwartym procesem :Jeśli trzeba zachować skorupę wokół jakiegoś powodu (tj. Trzeba zrobić porządki po serwer kończy), należy użyć kombinacji
trap
,wait
ikill
. Zobacz odpowiedź SensorSmith .źródło
Andreas Veithen zwraca uwagę, że jeśli nie musisz wracać z połączenia (jak w przykładzie PO), wystarczy zadzwonić za pomocą
exec
polecenia (odpowiedź @Stuart P. Bentley ). W przeciwnym razie „tradycyjny”trap 'kill $CHILDPID' TERM
(odpowiedź @ cuonglm) jest początkiem, alewait
wywołanie faktycznie powraca po uruchomieniu procedury obsługi pułapki, co może być jeszcze przed zakończeniem procesu potomnego. Dlategowait
wskazane jest „dodatkowe” połączenie z (odpowiedź @ user1463361 ).Chociaż jest to poprawa, nadal ma warunek wyścigu, co oznacza, że proces może nigdy nie zostać zakończony (chyba że sygnalizator spróbuje wysłać sygnał TERM). Okno podatności polega na zarejestrowaniu modułu obsługi pułapki i zarejestrowaniu PID dziecka.
Poniżej opisano tę lukę (zawartą w funkcjach do ponownego użycia).
źródło
Podane rozwiązanie nie działa dla mnie, ponieważ proces został zabity przed faktycznym zakończeniem polecenia czekania. Znalazłem ten artykuł http://veithen.github.io/2014/11/16/sigterm-propagation.html , ostatni fragment kodu działa dobrze w moim przypadku aplikacji uruchomionej w OpenShift z niestandardowym programem uruchamiającym sh. Skrypt sh jest wymagany, ponieważ muszę mieć możliwość zrzutów wątków, co jest niemożliwe w przypadku, gdy PID procesu Java wynosi 1.
źródło