Как правильно перехватить SIGQUIT в сценарии bash?
Вопрос
Я могу писать сценарии оболочки, которые прекрасно перехватывают код SIGINT
, но не могу перехватить код SIGQUIT
.
Выполнение этого скрипта и нажатие CTRL-C
дает желаемый эффект, но нажатие CTRL-\
(которое, как я понимаю, должно запускать SIGQUIT
) ничего не делает, кроме печати ^\
в терминале. Почему?
У меня есть две актуальные теории. Во-первых, семантика SIGINT
и SIGQUIT
отличается, так что SIGQUIT
отправляется только дочернему процессу sleep
, а SIGINT
отправляется как дочернему процессу, так и родительскому процессу bash. Если это так, где это задокументировано?
Моя вторая теория заключается в том, что bash по умолчанию не только игнорирует (т. е. не имеет обработчика для) SIGQUIT
(как предлагается на странице руководства), но и не позволяет ему вообще быть перехваченным. Эта теория пересекается с первой теорией, поскольку может случиться так, что SIGQUIT
будет передаваться как родительскому, так и дочернему, но родительский (bash
) просто не может его перехватить. Если это так, есть ли какой-нибудь способ перехватить код SIGQUIT
в сценарии bash? ... возможно, я могу установить какой-нибудь код shopt
?
Изменить: это на Ubuntu 10.10 в gnome-terminal 2.32.0 с запущенным bash 4.1.5, и да, ^\
настроен на выдачу SIGQUIT (как сообщает stty -a
и подтверждается выдачей SIGQUITs ^\
другим программам, таким как ping
) <. / p>
ОБНОВЛЕНИЕ:
Я только что обнаружил, что проблема должна быть каким-то образом связана с gnome-terminal. Если я запустил этот скрипт с виртуальной консоли (то есть, сгенерировал код для выхода из X), он отлично перехватит SIGQUIT, когда я нажму сгенерированный код. Тот же bash и все остальное, поэтому единственная разница должна заключаться в эмуляторе терминала. Итак, теперь мой вопрос таков: как я могу настроить gnome-terminal, чтобы он в этом отношении вел себя как виртуальная консоль? Я сгенерировал выходные данные ctrl-alt-f1
в виртуальной консоли и в gnome-terminal, и, хотя есть различия, ничего не кажется сразу актуальным (например, у них обоих есть ^\
).
ОБНОВЛЕНИЕ 2:
Еще один эксперимент. Просто выполните diff
в gnome-terminal; нажмите кнопку stty -a
, и сигнал не будет перехвачен. Теперь выполните в виртуальной консоли quit = ^\;
; нажмите $ sleep 60
и сигнал будет пойман - процесс распечатает код ^\
и завершится. Но теперь запустите $ sleep 60
в gnome-terminal и нажмите ^\
- сигнал будет пойман и обработан, как ожидалось. Так что в gnome-terminal есть что-то странное, так что SIGQUIT может быть пойман одними программами, но не другими, даже если другие действительно поймают его при вызове с виртуальной консоли. Возможно, мне стоит просто обновить свой gnome-terminal.
Решение
Могу только предположить, что это была какая-то ошибка в gnome-terminal 2.32.0;С тех пор я обновился до Ubuntu 11.04 с gnome-terminal 2.32.1 (и bash 4.2.8), а SIGQUIT теперь заблокирован, как и ожидалось.
Другие советы
Я наблюдаю то же поведение в Fedora 19 с XFCE: согласно ps s
, bash в xfce4-терминале игнорирует SIGQUIT, запускает yes >/dev/null &
, а затем ps s
показывает, что даже подпроцесс игнорирует SIGQUIT.Когда я (с того же терминала) запускаю ssh localhost
, оболочка в сеансе ssh также игнорирует SIGQUIT, а yes >/dev/null &
- нет.
Учитывая приведенный выше комментарий, в котором упоминается gnome-terminal, я предполагаю, что ошибка находится в общей части двух терминалов: в библиотеке vte
.Мой код генерирует код.