Polecenie trap

man trap

trap: trap [-lp] [[arg] sygnał ...]
    Przechwytywanie sygnałów i innych zdarzeń.
    
    Polecenie definiujące i włączające daną akcję w przypadku, kiedy powłoka
    otrzyma sygnał lub pod innymi warunkami.
    
    Gdy powłoka otrzyma podany SYGNAŁ (lub sygnały), odczytywane i uruchamiane
    jest polecenie podane jako argument ARG. W razie braku argumentu (i podaniu
    pojedynczego SYGNAŁU) lub gdy argumentem jest `-', każdemu z podanych
    sygnałów jest przywracane pierwotne zachowanie. Jeśli ARG jest pustym
    łańcuchem, każdy SYGNAŁ jest ignorowany przez powłokę i wywołane przez nią
    polecenia.
    
    Jeżeli jako SYGNAŁ podano EXIT (0), polecenie ARG jest uruchamiane przy
    opuszczaniu powłoki. Jeśli jako SYGNAŁ podano DEBUG, ARG jest uruchamiane
    po każdym poleceniu prostym. Jeśli jako SYGNAŁ podano RETURN, ARG jest
    uruchamiane przy każdym zakończeniu funkcji powłoki lub skryptu
    uruchamianego przez polecenia wbudowane . lub source. Jeśli jako SYGNAŁ
    podano ERR, ARG jest uruchamiane za każdym razem, kiedy niepowodzenie
    polecenia spowodowałoby zakończenie powłoki w przypadku włączenia opcji -e.
    
    Jeśli nie podano argumentów, trap wypisuje listę poleceń przypisanych do
    każdego sygnału.
    
    Opcje:
      -l        wypisanie listy nazw sygnałów i ich numerów
      -p        wypisanie poleceń trap powiązanych z każdym SYGNAŁEM
    
    Każdy podawany SYGNAŁ może być nazwą sygnału wg. <signal.h> lub numerem
    sygnału. Nazwy sygnałów są niewrażliwe na wielkość liter, a prefiks SIG
    jest opcjonalny. Sygnał do powłoki można wysłać poleceniem
    "kill -sygnał $$".
    
    Stan wyjściowy:
    Zwracana jest prawda, chyba że podano błędny SYGNAŁ lub błędną opcję.

Podpowiedź

Polecam równiez od razu zerknąć do manuala polecenia kill.

Przykłady użycia

#!/bin/bash
trap 'echo "Jestem kuloodporny, strzelaj sobie ..."' SIGINT
trap 'echo "Teraz już nie jestem kulodporny, możesz mnie unicestwić"; trap - SIGINT' SIGHUP

while : ; do
  echo "Moj PID to: $$ ; Naciśnij ^C (CTRL+C) aby wyjść"
  sleep 5
done
Konsola #1 Konsola #2

Uruchamiamy kod z powyższego przykładu i parę razy wysłalismy do programu sygnał SIGINT (^C) poprzez kombinację klawiszy (CTRL + C)

johny@ThinkPad:~$ bash trap.sh
Moj PID to: 10876 ; Naciśnij ^C (CTRL+C) aby wyjść
^C
Jestem kuloodporny, strzelaj sobie ...
Moj PID to: 10876 ; Naciśnij ^C (CTRL+C) aby wyjść
^C
Jestem kuloodporny, strzelaj sobie ...
Moj PID to: 10876 ; Naciśnij ^C (CTRL+C) aby wyjść
Moj PID to: 10876 ; Naciśnij ^C (CTRL+C) aby wyjść
Moj PID to: 10876 ; Naciśnij ^C (CTRL+C) aby wyjść
 
 

Wysyłamy do uruchomionego procesu sygnał SIGHUP

johny@ThinkPad:~$ kill -SIGHUP 10876

Sygnał zostraje przechwycony i program przy kolejnym sygnału SIGINT zachowa sie inaczej

Teraz już nie jestem kulodporny, możesz mnie unicestwić
Moj PID to: 10876 ; Naciśnij ^C (CTRL+C) aby wyjść
Moj PID to: 10876 ; Naciśnij ^C (CTRL+C) aby wyjść
^C
 

Pierwsze polecenie trap powoduje, że program na wysłanie sygnału SIGINT będzie reagował pierwszym komunikatem. Następna linijka mówi, że wysyłając sygnał SIGHUP skrypt również wypisze komunikat, ale też przypisze standardowe działanie dla sygnału SIGINT.

Tak więc początkowo naciskając klawisze ^C (CTRL + C) nie uda nam się zamknąć programu, ale wystarczy wysłać do procesu sygnał SIGHUP, by było to możliwe.

Aby wysłać do dowolnego procesu w systemie jakiś sygnał używamy polecenia kill.

W naszym przypadku będzie to polecenie kill -SIGHUP PID, gdzie PID to numer identyfikacyjny naszego procesu.

Ostrzeżenie

Pisząc zamiast polecenia myślnik przypisujemy sygnałowi domyślną akcję (np. trap - SIGINT).

Ostrzeżenie

  • Nie należy zapomnieć o pojedynczych cudzysłowach, choć nie są one niezbędne (kiedyś uzywano odwrotnych cudzysłowów)!
  • Do polecenia trap można przypisać dowolne polecenia a nawet funkcję! Co moze stwarzać bardzo duże możliwości.
  • Sygnał KILL (-9) nie może być zablokowany!