Как правильно перехватить SIGQUIT в скрипте bash? - PullRequest
3 голосов
/ 17 июня 2011

Я могу написать сценарии оболочки, которые просто перехватывают SIGINT, но я не могу перехватить SIGQUIT.

#!/bin/bash

function die {
    echo "Dying on signal $1"
    exit 0
}

trap 'die "SIGINT"' SIGINT
trap 'die "SIGQUIT"' SIGQUIT

while true; do
    echo "sleeping..."
    sleep 5
done

Выполнение этого сценария и нажатие CTRL-C дает желаемый эффект,но нажатие CTRL-\ (которое, как я понимаю, должно вызвать SIGQUIT) ничего не делает, кроме печати ^\ в терминале.Почему?

У меня есть две действующие теории.Во-первых, семантика SIGINT и SIGQUIT отличается тем, что SIGQUIT отправляется только дочернему процессу sleep, тогда как SIGINT отправляется как дочернему процессу, так и родительскому процессу bash.Если это так, то где это задокументировано?

Моя вторая теория заключается в том, что bash не только игнорирует (т. Е. Имеет неработающий обработчик для) SIGQUIT по умолчанию (как предполагает страница man),но не позволяет ему быть пойманным в ловушку вообще.Эта теория пересекается с первой теорией, так как может быть так, что SIGQUIT направляется как к родителю, так и к ребенку, но родитель (bash) просто не может ее перехватить.Если это так, есть ли любой способ перехвата SIGQUIT в скрипте bash? ... возможно, какой-нибудь shopt, который я могу установить?

Редактировать: это на Ubuntu10.10 в gnome-Terminal 2.32.0 работает Bash 4.1.5, и да ^\ настроен на выдачу SIGQUIT (как сообщается stty -a и подтверждается путем выдачи ^\ SIGQUIT для других программ, таких как ping).

ОБНОВЛЕНИЕ: Я только что обнаружил, что проблема должна быть как-то из-за gnome-терминала.Если я запускаю этот скрипт с виртуальной консоли (то есть ctrl-alt-f1, чтобы выйти из X), он прекрасно перехватывает SIGQUIT, когда я нажимаю ^\.Тот же bash и все, поэтому единственное отличие должно быть эмулятором терминала.Итак, теперь у меня возникает вопрос: как я могу настроить gnome-терминал, чтобы он вел себя как виртуальная консоль в этом отношении?Я diff сделал вывод stty -a в виртуальной консоли и в gnome-терминале, и, хотя есть различия, ничто не кажется актуальным (например, они оба имеют quit = ^\;).

ОБНОВЛЕНИЕ2: другой эксперимент.Просто выполните $ sleep 60 в gnome-терминал;нажмите ^\ и сигнал останется необработанным.Теперь выполните $ sleep 60 в виртуальной консоли;нажмите ^\ и сигнал будет перехвачен - процесс напечатает Quit и выйдет.Но теперь запустите $ ping google.com в gnome-терминал и нажмите ^\ - сигнал перехватывается и обрабатывается, как и ожидалось.Так что в gnome-terminal есть что-то странное, так что SIGQUIT может быть перехвачен некоторыми программами, но не другими, даже если другие do перехватят его при вызове из виртуальной консоли.Возможно, я должен просто обновить свой gnome-терминал.

Ответы [ 2 ]

2 голосов
/ 19 июня 2011

Я могу только предположить, что это была какая-то ошибка в gnome-terminal 2.32.0;С тех пор я обновился до Ubuntu 11.04 с терминалом gnome 2.32.1 (и bash 4.2.8), и теперь SIGQUIT перехвачен, как и ожидалось.

0 голосов
/ 17 октября 2013

Я наблюдаю такое же поведение на Fedora 19 с XFCE: согласно ps s, bash в терминале xfce4 игнорирует SIGQUIT, работает yes >/dev/null &, а затем ps s показывает, что даже подпроцесс игнорирует SIGQUIT.Когда я (из того же терминала) запускаю ssh localhost, оболочка в сеансе ssh также игнорирует SIGQUIT, но yes >/dev/null & нет.

Учитывая приведенный выше комментарий, в котором упоминается gnome-терминал, я бы предположилошибка в общей части двух терминалов: библиотека vte.Мой vte-0.28.2-9.fc19.x86_64.

...