Linux. Команда trap
Сигналы — это числовые сообщения, которые посылаются запущенным приложениям операционной системой, другими приложениями или пользователем. Сигналы, как правило, ожидают от приложения какой-то определённой реакции, например «корректно завершить работу», «приостановить работу» или «умри!».
Обычно для отправки сигналов приложениям используется программа kill
, но некоторые сигналы можно отправлять и при помощи клавиатурных комбинаций, например Ctrl+C
или Ctrl+Z
.
Сигналы обрабатываются «каскадно». То есть, сигнал отправляется приложению и, если приложение не обработало поступивший сигнал, то он возвращается обратно оболочке или операционной системе. Некоторые типы сигналов в принципе не могут обрабатываться приложениями. Например, сигнал SIGKILL
вообще не доставляется приложению, а перехватывается операционной системой, которая немедленно завершает работу приложения, которому сигнал был адресован.
Могут быть ситуации, когда нежелательно, чтобы пользователи прерывали работу сценария, например с помощью Ctrl+C
. Поскольку нужно освободить входной поток или удалить временные файлы. Команда trap
позволяет перехватить сигнал до того, как он удалит процесс и выполнить некоторое дополнительное или альтернативное действие.
$ trap действие сигнал(ы)
Команда trap
работает довольно просто — при возникновении сигнала будет выполнено указанное действие. Если действие простое (цепочка команд, умещающаяся на одной строке), его можно указать прямо в аргументе trap
. Если не очень простое, то надо объявить функцию и поместить вызов этой функции в trap
.
Если действие по умолчанию для сигнала было изменено с помощью trap
, его можно восстановить с помощью все той же команды trap
— надо опустить первый аргумент или заменить его дефисом:
$ trap сигнал(ы)
$ trap - сигнал(ы)
Для игнорирования сигналов команде trap
надо передать пустую строку в качестве первого аргумента. Скрипт ниже можно прервать только смертоносным сигналом SIGKILL
:
#!/bin/bash
trap '' SIGHUP SIGINT SIGQUIT SIGTERM
sleep 60
Вызов trap
без аргументов напечатает все установленные обработчики сигналов, это полезно при отладке.
Сигналы
- Сигнал SIGHUP (номер 1) изначально был предназначен для того, чтобы информировать программу о потере связи с управляющим терминалом. Этот сигнал посылается процессам и в случае закрытия виртуальных терминалов, которые используются на современных системах вместо аппаратных терминалов. Обычным действием по умолчанию для
SIGHUP
является перечитывание конфигурации без остановки. - Сигнал SIGINT (номер 2) посылается процессу, если пользователь терминала дал команду прервать процесс (обычно это сочетание клавиш
Ctrl+C
). - Сигнал SIGQUIT (номер 3) посылается процессу, если пользователь терминала дал команду остановить процесс комбинацией «quit» (обычно это сочетание клавиш
Ctrl+\
). Этот сигнал также указывает, что система должна выполнить дамп памяти для процесса. - Сигнал SIGKILL (номер 9) завершает работу программы. Программа не может ни обработать, ни игнорировать этот сигнал.
- Сигнал SIGPIPE (номер 13) посылается процессу при записи в соединение (pipe, socket) при отсутствии или обрыве соединения с другой (читающей) стороной.
- Сигнал SIGTERM (номер 15) вызывает «вежливое» завершение программы. Получив этот сигнал, программа может выполнить необходимые перед завершением операции (например, высвободить занятые ресурсы). Получение
SIGTERM
свидетельствует не об ошибке в программе, а о желании ОС или пользователя завершить ее. - Сигнал SIGCONT (номер 18) возобновляет выполнение процесса, остановленного сигналом
SIGSTOP
или сигналомSIGTSTP
. - Сигнал SIGSTOP (номер 19) приостанавливает выполнение процесса. Как и
SIGKILL
, этот сигнал невозможно перехватить или игнорировать. - Сигнал SIGTSTP (номер 20) приостанавливает процесс по команде пользователя (обычно это сочетание клавиш
Ctrl+Z
). Для возобновления выполнения используется сигналSIGCONT
.
Список всех сигналов
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Примеры
Сценарий будет выполняться до тех пор, пока не получит сигнал SIGINT
(нажатие Ctrl+C
):
#!/bin/bash
count=0
trap 'echo "Получен сигнал SIGINT (нажатие Ctrl+C), завершение сценария"; exit 1' SIGINT
while true ; do
sleep 1
(( count++ ))
echo $count
done
Удаление временного файла с помощью функции, которая передается в качестве первого аргумента команде trap
:
#!/bin/bash
cleanup() {
rm $TEMP_FILE
exit $?
}
TEMP_FILE=/tmp/tempfile.$$.$RANDOM
trap cleanup SIGHUP SIGINT SIGQUIT SIGTERM
# Делаем что-то...
Поиск: Bash • CLI • SIGCONT • SIGHUP • SIGINT • SIGKILL • SIGQUIT • SIGSTOP • SIGTERM • SIGTSTP • trap • Команда • Сигнал