Skrypty powłoki Bash #13 - Sygnały co coś znaczyć miały
Wstęp
Dzień dobry, dziś opowiem o sygnałach, które może otrzymać wasz program oraz jak je obsłużyć.
Co to jest Sygnał?
Sygnał jest, to przerwanie na poziomie oprogramowania, rodzaj komunikacji między procesami. Sygnały mają u standaryzowane znaczenie, a każdy posiada swój kod, który możemy obsłużyć.
Jakie mamy sygnały
Mamy do dyspozycji wiele sygnałów, zdefiniowanych w dokumencie POSIX, ale my zajmiemy, się ich oryginalnym zestawem, by ograniczyć się tylko, do tych najczęściej spotykanych. Sygnały, które znajdziecie w tabeli niżej, dzielą się na 5 typów, z czego 3 znajdują się w tabeli. Są to : Term,Ign,Core,Stop,Cont. Gdzie domyślnie Term zatrzymuje program, Ign oznacza Ignoruj, czyli jest to sygnał czysto informacyjny, Core - zatrzymaj program i “zrzuć” aktualny stan pamięci. Stop - zatrzymaj/za pauzuj pracę, Cont - kontynuuj pracę programu.
Sygnał | Kod | Typ działania | Komentarz |
---|---|---|---|
SIGHUP | 1 | Term | Wykryto zawieszenie sesji kontrolującej lub śmierć procesu nadrzędnego/kontrolującego |
SIGINT | 2 | Term | Przerwanie podany z klawiatury (domyślnie ‘ctrl+c’) |
SIGQUIT | 3 | Core | sygnał “wyjścia” podany z klawiatury (domyślnie ‘ctrl+') |
SIGILL | 4 | Core | Niedozwolona/nieznana instrukcja |
SIGABRT | 6 | Core | Sygnał zatrzymania z komendy abort (man 3 abort) |
SIGFPE | 8 | Core | błąd operacji arytmetycznych (np. dzielenie przez 0) |
SIGKILL | 9 | Term | sygnał “zabójstwa”, natychmiast zatrzymuje program (Nie można go obsłużyć) |
SIGSEGV | 11 | Core | Nie poprawne odwołanie do pamięci |
SIGPIPE | 13 | Term | Próba zapisu do potoku, który nie ma odbiorców (przeczytaj więcej w man 7 pipe) |
SIGALRM | 14 | Term | Sygnał zegara z komendy alarm (man 2 alarm) |
SIGTERM | 15 | Term | Sygnał zakończenia |
SIGUSR1 | 30,10,16 | Term | Sygnał definiowany, przez użytkownika 1 |
SIGUSR2 | 31,12,17 | Term | Sygnał definiowany, przez użytkownika 2 |
SIGCHLD | 20,17,18 | Ign | Proces potomny zatrzymany, lub zakończony. |
Jak możemy obsłużyć sygnał
Obsługę sygnału, możemy uzyskać poprzez polecenie trap
. Jego zadaniem jest wykonanie danej czynności dla danego sygnału i tak np.
trap "cleanup; exit 1" INT
oznacza “Gdy otrzymasz sygnał SIGINT, wykonaj funkcję/program cleanup i zakończ program z kodem wyjścia 1”
W języku skryptowym bash, przerwania działają synchronicznie , czyli obsługa przerwania, zostanie wykonana dopiero w momencie zakończenia jednej komendy. Np. mamy program, który uruchamiamy z naszego skryptu, bo musimy po dodawać jakieś zmienne i nasz skrypt jest “rodzicem” (procesem nadrzędnym) tego programu. Więc nasz skrypt nie obsłuży przerwania (poza SIGKILL) doputy, dopóki program potomny się nie zakończy!
Dlatego też polecam, do programów w tle pisać programy okalające (eng. wrapper/ korp. wrappery) w językach tj. C, perl, python, lua, go, rust, java, scala, haskel …. byle nie w shellu, bo inaczej, będzie problem z tzw. łagodnym zamykaniem.
Przykładowa obsługa sygnału
Tutaj prosty przykładowy kod, by pokazać, jak można wykorzystać komendę trap
#!/bin/bash
cleanup() {
echo "otrzymałem sygnał ${1}, kończę działanie"
rm /tmp/plik_do_pracy
rm /tmp/jakis_plik_lock
echo "czyszczenie zakończone"
}
trap 'cleanup "2"; exit 2' INT
trap 'cleanup "HUP" ;exit 1' 1
while [ true ]; do
echo "petla na amen"
sleep 5
done
Epilog
W tym krótkim poście, chciałem was zaznajomić z komendą ‘trap’ i obsługą sygnałów. Tak naprawdę sama obsługa sygnałów jest bardzo prosta, tylko trzeba pamiętać, że sygnału 9 (SIGKILL) obsłużyć nie można. Dodatkowo proszę, pamiętajcie, jeżeli puszczacie coś w tło czy robicie coś na Dockerze, starajcie się napisać “starter” w czymś innym niż shell, chyba że kontener może spokojnie umrzeć i nic się nie stanie (czyli w większości przypadków ) Trzymajcie się, miłego dnia i smacznej kawusi :)
Pozdrawiam.
Pozdrawiam