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