Когда HUP прекратил отправку и что я могу с этим сделать?

В то время, когда я был молод, и Unix был новинкой, создание процесса, который не был убит, когда вы вышли из системы, было сложной задачей. Мы использовали команду nohup для защиты наших постоянных процессов от HUP сигнал. Если мы не будем осторожны, наши процессы будут убиты, когда мы выйдем из системы или даже закроем оболочку, из которой мы их запустили.

Перенесемся в сегодняшний день, и я нахожу, что я удивлен, что дефолт выглядит как раз наоборот. Как в Ubuntu, так и в системах Red Hat я обнаружил, что могу поместить практически любой процесс в фоновый режим, убить родительскую оболочку, выйти из системы и т.д. Я вижу такое же поведение со скриптами Bash, скриптами Python и программами на Си. Я получаю такое же поведение от сеансов xterm или ssh.

Например, в окне xterm или ssh введите:

while [ 1 ]; do date; sleep 10; done > /tmp/out &

Теперь из другого окна беги

tail -f /tmp/out

Наблюдайте, как она печатает дату каждые 10 секунд, затем закройте исходную родительскую оболочку с помощью Ctrl-D. Все еще работает. Выйдите из системы и вернитесь обратно. Все еще работает.

Отправить это HUP сигнал, он мгновенно умирает.

Я могу продемонстрировать то же поведение с помощью скрипта Python или C-программы. Спать или нет не имеет значения. Например, эта уродливая программа на С ведет себя так же:

#include <stdio.h>

void main() {
    while(1) {
        printf("*\n");
        fflush(stdout);
        int i, j, k = 0;
        for(i=0; i < 10000; i++) {
            for(j=0; j < 100000; j++) {
                k += i * j;
            }
        }
    }
}

Это полностью противоречит путям моей юности. Я думаю, я просто не заметил, когда это изменилось? Кто-нибудь из историков знает, когда это произошло? Есть ли HUP даже привыкнуть к этому больше?

Если это действительно так, то мой вопрос: как я могу устроить процесс, который умирает, когда пользователь выходит из системы или отключается?

У меня есть взлом, который включает в себя наблюдение за ppid (родительский пид), чтобы изменить, но, конечно, есть что-то более элегантное, чем это.

2 ответа

Решение

Я полагаю, что вы ищете huponexit вариант оболочки. Вы можете установить это легко с

$ shopt -s huponexit

Некоторые подробности со страницы руководства bash:

Оболочка выходит по умолчанию при получении SIGHUP. Перед выходом интерактивная оболочка отправляет SIGHUP всем работам, запущенным или остановленным. Остановленные задания отправляются SIGCONT, чтобы гарантировать получение SIGHUP. Чтобы не дать оболочке отправлять сигнал на конкретное задание, его следует удалить из таблицы заданий с помощью встроенной команды disown (см. Ниже КОМАНДЫ ПОСТРОЕНИЯ ОБОЛОЧКИ) или отметить, что она не получает SIGHUP с помощью команды disown -h.

Если параметр оболочки huponexit был установлен с помощью shopt, bash отправляет SIGHUP всем работам при выходе из интерактивной оболочки входа в систему.

Я все еще получаю вздох. Простой способ проверить:

#!/usr/bin/env sh

echo "$$"
trap "echo HUPPED $$ > /tmp/willithup" HUP
sleep 1000

Затем закройте эмулятор терминала. Теперь вернемся к вашему вопросу:

Наблюдайте, как она печатает дату каждые 10 секунд, затем закройте исходную родительскую оболочку с помощью Ctrl-D. Все еще работает. Выйдите из системы и снова войдите.

Процесс не получает HUP, когда его родитель умирает. Он получает HUP, когда теряет соединение с управляющим терминалом или когда ему явно отправляется HUP. Это происходит, например, когда вы выходите из SSH.

Если мы не будем осторожны, наши процессы будут убиты, когда мы выйдем из системы или даже закроем оболочку, из которой мы их запустили

Во-вторых, оболочка может отправлять HUP всем своим дочерним элементам при выходе. Однако Bash, например, имеет huponexit по умолчанию установлено значение false. Это вполне может быть то, что изменилось. Обратите внимание, что независимо от опции huponexit, когда она получает HUP, оболочка также отправляет HUP всем своим дочерним элементам.


По словам Стивенса:

Сеанс может иметь один управляющий терминал. Обычно это терминальное устройство (в случае входа в систему с терминала) или псевдотерминальное устройство (в случае входа в сеть), на котором мы выполняем вход.

Если через интерфейс терминала обнаружено разъединение модема (или сети), сигнал зависания отправляется управляющему процессу (руководителю сеанса).


Для дальнейшего уточнения начальный HUP не отправляется оболочкой. Отправляется драйвером терминала. После этого снаряд "направляет" его детям. Таким образом, HUP, отправленный драйвером терминала, может "каскадно" работать. Из ТЛПИ:

Когда управляющий процесс теряет свое терминальное соединение, ядро ​​посылает ему сигнал SIGHUP, чтобы сообщить ему об этом факте. (Сигнал SIGCONT также отправляется, чтобы гарантировать, что процесс перезапускается в случае, если он был ранее остановлен сигналом.) Как правило, это может произойти в двух случаях:

  • Когда драйвер терминала обнаруживает "разъединение", что указывает на потерю сигнала на модеме или на терминальной линии.
  • Когда окно терминала закрыто на рабочей станции. Это происходит потому, что последний открытый дескриптор файла для главной стороны псевдотерминала, связанного с окном терминала, закрыт.
Другие вопросы по тегам