Про команду kill
и сигналы управления процессами (SIGKILL
, SIGTERM
и другие) можно прочитать в статье Linux&FreeBSD: команды kill, nohup — сигналы и управление процессами.
У bash
имеется встроенная команда trap
, которая может перехватывать такие команды и выполнять какие-либо действия, заданные ей.
Синтаксис команды:
trap command signals
command
– что именно необходимо выполнить при перехвате сигнала;
signals
– список сигналов, которые необходимо перехватывать. Сигналы можно указывать как в полном виде – SIGTERM
, так и в виде кода – 1, 2 и т.д.
Рассмотрим простой пример скрипта, в котором цикл будет выполняться до тех пор, пока не получит сигнал Ctrl+C (SIGINT
– interrupt) или не достигнет значения 100 для переменной $count
:
$ cat trap-1.sh #!/bin/bash count=0 trap 'echo "Exit"; exit 1' 2 while [ $count -lt 100 ] do sleep 1 (( count++ )) echo $count done
Про циклы читайте в статье BASH: описание циклов for, while, until и примеры использования.
Пример его выполнения:
$ ./trap-1.sh 1 2 3 Exit
После получения сигнала SIGINT
(Ctrl+C) trap
выполнил команду 'echo "Exit"'
и сразу за ней – "exit 1"
, завершив работу скрипта. В этом примере сигнал, который надо перехватить задан в виде кода – SIGINT
= 2 и т.д.
Список кодов наиболее используемых сигналов в таблице ниже:
Signal Name | Signal Number | Description |
---|---|---|
SIGHUP | 1 | Hang up detected on controlling terminal or death of controlling process |
SIGINT | 2 | Issued if the user sends an interrupt signal (Ctrl + C). |
SIGQUIT | 3 | Issued if the user sends a quit signal (Ctrl + D). |
SIGFPE | 8 | Issued if an illegal mathematical operation is attempted |
SIGKILL | 9 | If a process gets this signal it must quit immediately and will not perform any clean-up operations |
SIGALRM | 14 | Alarm Clock signal (used for timers) |
SIGTERM | 15 | Software termination signal (sent by kill by default). |
Команде trap
можно передавать список сигналов, разделённые пробелами:
trap 'echo "Exit"; exit 1' 1 2 3 15
В качестве команды trap
может принимать функции. Возьмём пример функции answer
и немного переделаем наш скрипт:
$ cat trap.sh #!/bin/bash count=0 answer () { while read response; do echo case $response in [yY][eE][sS]|[yY]) printf "$1n" return 0 #$2 break ;; [nN][oO]|[nN]) printf "$2n" return 1 #$4 break ;; *) printf "Please, enter Y(yes) or N(no)! " esac done } trap 'printf "Are you sure to skip? [Y/n] "; answer && printf "nSkipping...nn" && exit 1 ' SIGINT while [ $count -lt 100 ] do sleep 1 (( count++ )) echo $count done
Тут мы задали сигнал в виде имени – SIGINT
. Посмотрим, как выполняется такой скрипт:
$ ./trap.sh 1 2 3 Are you sure to skip? [Y/n] n 4 5 6 Are you sure to skip? [Y/n] y Skipping...
Таким же образом можно заставить скрипт игнорировать полученные сигналы (кроме kill -9 - "SIGKILL"
, который уничтожит процесс в любом случае). Для это вместо команды – просто укажите пустые одинарные кавычки – ''
. Пример:
$ cat trap-2.sh #!/bin/bash count=0 trap '' 2 while [ $count -lt 100 ] do sleep 1 (( count++ )) echo $count done
$ ./trap-2.sh 1 2 3 ... 18 19 20 Terminated
Процесс нельзя будет прервать комбинацией Ctrl+C, но он был прерван командой kill
(SIGTERM
, код 15 используется kill
по-умолчанию).
Если же добавить код 15:
trap '' 2 15
То прервать выполнение можно будет только с помощью kill -9
.