Про команду 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.