BASH: использование команды trap для перехвата сигналов прерывания процесса
By мережевий хробачок™ | 11/20/2013
0 Comments
Про команду kill и сигналы управления процессами (SIGKILL, SIGTERM и другие) можно прочитать в статье Linux&FreeBSD: команды kill, nohup — сигналы и управление процессами.
У bash имеется встроенная команда trap, которая может перехватывать такие команды и выполнять какие-либо действия, заданные ей.
Синтаксис команды:
trap command signals
command – что именно необходимо выполнить при перехвате сигнала;
signals – список сигналов, которые необходимо перехватывать. Сигналы можно указывать как в полном виде – SIGTERM, так и в виде кода – 1, 2 и т.д.
Рассмотрим простой пример скрипта, в котором цикл будет выполняться до тех пор, пока не получит сигнал Ctrl+C (SIGINT – interrupt) или не достигнет значения 100 для переменной $count:
05 |
trap 'echo "Exit"; exit 1' 2 |
07 |
while [ $count -lt 100 ] |
Про циклы читайте в статье BASH: описание циклов for, while, until и примеры использования.
Пример его выполнения:
После получения сигнала 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 можно передавать список сигналов, разделённые пробелами:
1 |
trap 'echo "Exit"; exit 1' 1 2 3 15 |
В качестве команды trap может принимать функции. Возьмём пример функции answer и немного переделаем наш скрипт:
06 |
while read response; do |
22 |
printf "Please, enter Y(yes) or N(no)! " |
27 |
trap 'printf "Are you sure to skip? [Y/n] "; answer && printf "nSkipping...nn" && exit 1 ' SIGINT |
29 |
while [ $count -lt 100 ] |
Тут мы задали сигнал в виде имени – SIGINT. Посмотрим, как выполняется такой скрипт:
06 |
Are you sure to skip? [Y/n] n |
12 |
Are you sure to skip? [Y/n] y |
Таким же образом можно заставить скрипт игнорировать полученные сигналы (кроме kill -9 - "SIGKILL", который уничтожит процесс в любом случае). Для это вместо команды – просто укажите пустые одинарные кавычки – ''. Пример:
07 |
while [ $count -lt 100 ] |
Процесс нельзя будет прервать комбинацией Ctrl+C, но он был прерван командой kill (SIGTERM, код 15 используется kill по-умолчанию).
Если же добавить код 15:
view source
То прервать выполнение можно будет только с помощью kill -9.