Bash
Использование «ловушки» для реагирования на сигналы и системные события
Поиск…
Синтаксис
- trap action sigspec ... # Запустить «действие» в списке сигналов
- trap sigspec ... # Опуская действие сбрасывает ловушки для сигналов
параметры
параметр | Имея в виду |
---|---|
-п | Список установленных ловушек |
-l | Имена списков и соответствующие номера |
замечания
Утилита trap
- специальная встроенная оболочка. Он определен в POSIX , но bash добавляет некоторые полезные расширения.
Примеры, совместимые с POSIX, начинаются с #!/bin/sh
, а примеры, начинающиеся с #!/bin/bash
используют расширение bash.
Сигналами могут быть либо номер сигнала, имя сигнала (без префикса SIG), либо специальное ключевое слово EXIT
.
Гарантируются POSIX:
Число | название | Заметки |
---|---|---|
0 | ВЫХОД | Всегда запускать на выходе оболочки, независимо от кода выхода |
1 | SIGHUP | |
2 | SIGINT | Это то, что посылает ^C |
3 | SIGQUIT | |
6 | SIGABRT | |
9 | SIGKILL | |
14 | SIGALRM | |
15 | SIGTERM | Это то, что kill по умолчанию |
Захват SIGINT или Ctl + C
Ловушка сбрасывается для подоболочек, поэтому sleep
будет по-прежнему действовать на сигнал SIGINT
отправленный ^C
(обычно путем выхода из игры), но родительский процесс (то есть сценарий оболочки) не будет.
#!/bin/sh
# Run a command on signal 2 (SIGINT, which is what ^C sends)
sigint() {
echo "Killed subshell!"
}
trap sigint INT
# Or use the no-op command for no output
#trap : INT
# This will be killed on the first ^C
echo "Sleeping..."
sleep 500
echo "Sleeping..."
sleep 500
И вариант, который по-прежнему позволяет вам выйти из основной программы, дважды нажав ^C
дважды:
last=0
allow_quit() {
[ $(date +%s) -lt $(( $last + 1 )) ] && exit
echo "Press ^C twice in a row to quit"
last=$(date +%s)
}
trap allow_quit INT
Введение: очистка временных файлов
Вы можете использовать команду trap
для «ловушки» сигналов; это эквивалент оболочки signal()
или sigaction()
в C и большинстве других языков программирования для улавливания сигналов.
Одним из наиболее распространенных способов использования trap
является очистка временных файлов как от ожидаемого, так и от неожиданного выхода.
К сожалению, недостаточно скриптов оболочки делают следующее :-(
#!/bin/sh
# Make a cleanup function
cleanup() {
rm --force -- "${tmp}"
}
# Trap the special "EXIT" group, which is always run when the shell exits.
trap cleanup EXIT
# Create a temporary file
tmp="$(mktemp -p /tmp tmpfileXXXXXXX)"
echo "Hello, world!" >> "${tmp}"
# No rm -f "$tmp" needed. The advantage of using EXIT is that it still works
# even if there was an error or if you used exit.
Накопите список ловушек для работы при выходе.
Вы когда-нибудь забыли добавить trap
для очистки временного файла или выполнить другую работу при выходе?
Вы когда-нибудь устанавливали одну ловушку, которая отменяла другую?
Этот код упрощает добавление вещей, которые нужно выполнять при выходе из одного элемента за раз, вместо того, чтобы иметь один большой оператор trap
где-то в вашем коде, что может быть легко забыть.
# on_exit and add_on_exit
# Usage:
# add_on_exit rm -f /tmp/foo
# add_on_exit echo "I am exiting"
# tempfile=$(mktemp)
# add_on_exit rm -f "$tempfile"
# Based on http://www.linuxjournal.com/content/use-bash-trap-statement-cleanup-temporary-files
function on_exit()
{
for i in "${on_exit_items[@]}"
do
eval $i
done
}
function add_on_exit()
{
local n=${#on_exit_items[*]}
on_exit_items[$n]="$*"
if [[ $n -eq 0 ]]; then
trap on_exit EXIT
fi
}
Убийство детских процессов на выходе
Выражения Trap не должны быть отдельными функциями или программами, они также могут быть более сложными выражениями.
Объединив jobs -p
и kill
, мы можем убить все порожденные дочерние процессы оболочки при выходе:
trap 'jobs -p | xargs kill' EXIT
реагировать на изменение размера окна терминала
Существует сигнал WINCH (WINdowCHange), который запускается при изменении размера окна терминала.
declare -x rows cols
update_size(){
rows=$(tput lines) # get actual lines of term
cols=$(tput cols) # get actual columns of term
echo DEBUG terminal window has no $rows lines and is $cols characters wide
}
trap update_size WINCH