2012-02-22 23 views
5

Mam skrypt bash „skrypt”, który z grubsza wygląda tak:bash rura SIGTERM

#!/bin/bash 

cmd1 | cmd2 | cmd3 

Kiedy robię kill script (lub bardziej precyzyjnie, gdy robię „scenariusz zatrzymania” w supervisord), nie wszystkie cmd * są zabijane. Jak mogę się upewnić, że są one zakończone wraz ze skryptem, który je zainicjował?

+0

Może powinien być na [su]? –

Odpowiedz

5

Supervisord ma opcję killasgroup (domyślnie wartość false), która określa, czy propagować sygnały stop/zakończenia do procesów potomnych.

[program:script] 
command=script 
killasgroup=true 

https://github.com/Supervisor/supervisor/blob/master/supervisor/process.py#L354

+0

Wygląda bardzo obiecująco, chociaż nie mogę tego w tej chwili przetestować: dodałem do wszystkich moich skryptów sprawdzanie oparte na "rodzicielskim pidzie", więc procesy potomne wychodzą same z siebie, gdy proces macierzysty się zmienia (najprawdopodobniej na "1"). – jldupont

+2

* (Sugerowana zmiana z Anonimu przeniesiona do komentarza) * Prawdopodobnie będziesz chciał także ustawić opcję true dla opcji stopasgroup, aby mieć pewność, że to zachowanie będzie używane w każdej sytuacji (na przykład przy poleceniu "restart"). Zauważ, że te opcje nie występują w starszych wersjach superwizora. – Andomar

2

Nie wiesz, jak używać supervisord, ale z pkill możesz użyć opcji -P, aby zabić od procesu nadrzędnego do wszystkich dzieci. Oto drzewa procesów (zaczynając od mojego działającego demona ssh).

$ pstree -a -p 1792 
sshd,1792 
    ├─sshd,27150 
    │ └─sshd,27153 
    │  └─zsh,27154 
    │   └─test.sh,27325 ./test.sh 
    │    └─cat,27326 
    └─sshd,27182 
     └─sshd,27184 
      └─zsh,27185 
       └─pstree,27357 -a -p 1792 

W jednej sesji Mam skrypt test.sh z pid 27325, aw drugiej biegnę polecenia pstree -a -p 1792 (bo sshd miał pid 1792)

A potem biegnę pkill -TERM -P 27325:

$ pstree -a -p 1792 
sshd,1792 
    ├─sshd,27150 
    │ └─sshd,27153 
    │  └─zsh,27154 
    └─sshd,27182 
     └─sshd,27184 
      └─zsh,27185 
       └─pstree,27387 -a -p 1792 

Ta odpowiedź została zasadniczo rephrased od tej drugiej odpowiedzi na stackoverflow: https://stackoverflow.com/a/392155/263969

+0

+1 Interesujące, ale nie dokładnie to, czego potrzebuję. – jldupont

0

Innym rozwiązaniem jest pułapka SIGTERM i zabić wszystkie dzieci w pułapkę kodu.

Jedyną rzeczą jest to, że powłoka uruchamia kod pułapki dla odebranego sygnału dopiero po zakończeniu wykonywanego polecenia - w twoim przypadku samo to nie pomogłoby.

Jednak pułapki będą uruchamiane w sposób "asynchroniczny", jeśli powłoka jest w "oczekiwaniu".

#!/usr/bin/env bash 
trap 'kill 0' TERM 
(cmd1 | cmd2 | cmd3) & wait 

kill 0 wysyła SIGTERM do wszystkich procesów, w bieżącej grupie procesu.

UWAGA: Mówię tutaj o Bash.