Убивает ли linux фоновые процессы, если мы закрываем терминал, с которого он начался?
у меня есть встроенная система, на которой я делаю telnet
и затем я запускаю приложение в фоновом режиме:
./app_name &
теперь, если я закрою терминал и сделать telnet
С другого терминала, и если я проверю, то я вижу, что этот процесс все еще работает.
чтобы проверить это, я написал небольшую программу:
#include<stdio.h>
main()
{
while(1);
}
Я запустил эту программу на своем локальном ПК linux в фоновом режиме, и я закрыл терминал.
теперь, когда я проверил этот процесс от других терминал тогда я обнаружил, что этот процесс также был убит.
мой вопрос:
- почему неопределенное поведение для одного и того же типа процесса?
- от чего он зависит?
- зависит ли это от версии Linux?
4 ответов
кто должен убивать Джобса?
обычно передние и фоновые задания убиваются SIGHUP
отправлено ядром или оболочкой в разных обстоятельствах.
когда ядро отправляет SIGHUP
?
ядро передает SIGHUP
to контролировать процесс:
- для реального (аппаратного) терминала: при обнаружении отключения в драйвере терминала, например, при зависании на модеме линия;
- for псевдотерминала (pty): когда последний дескриптор, ссылающийся на главную сторону pty, закрыт, например, при закрытии окна терминала.
ядро передает SIGHUP
для других групп процессов:
- to группа процессов переднего плана, когда контролировать процесс прекращается;
- to процесс осиротевшая группа, когда он становится сиротой и это остановило членов.
процесс управления является лидером сеанса, который установил соединение с управляющим терминалом.
как правило, процесс управления-это ваша оболочка. Итак, подводя итог:
- ядро посылает
SIGHUP
к оболочке, когда реальный или псевдотерминальный отключен / закрыт; - ядро посылает
SIGHUP
к группе процесса переднего плана когда раковина завершает; - ядро посылает
SIGHUP
в потерянную группу процессов, если она содержит остановленные процессы.
обратите внимание, что ядра не отправить SIGHUP
в фоновую группу процессов, если она не содержит остановленных процессов.
когда bash
отправить SIGHUP
?
Баш передает SIGHUP
to все задания (передний план и фон):
- при получении
SIGHUP
, и это интерактивная оболочка (и Контрольная работа поддержка включена во время компиляции); - когда она выходит, это интерактивная оболочка входа в систему, и
huponexit
опция установлена (и Контрольная работа поддержка включена во время компиляции).
Посмотреть подробнее здесь.
Примечания:
-
bash
не отправитьSIGHUP
для заданий, удаленных из списка заданий с помощьюdisown
; - процессы начали использовать
nohup
игнорироватьSIGHUP
.
более подробная информация здесь.
как насчет других снарядов?
обычно оболочки распространяются SIGHUP
. Генерация SIGHUP
при нормальном выходе встречается реже.
Telnet или SSH
под telnet или SSH, следующее должно произойти, когда соединение закрыто (например, когда вы закрываете telnet
окно на ПК):
- клиент убил;
- сервер обнаруживает, что клиентское соединение закрыто;
- сервер закрывает главную сторону pty;
- ядро обнаруживает, что master pty закрыт и отправляет
SIGHUP
tobash
; -
bash
получаетSIGHUP
, передаетSIGHUP
для всех заданий и завершается; - каждый получает задание
SIGHUP
и завершается.
я могу воспроизвести проблему с помощью bash
и telnetd
С busybox
или dropbear
SSH-сервер: иногда, фоновое задание не получает SIGHUP
(и не завершается), когда клиентское соединение закрыто.
кажется гонки возникает, когда сервер (telnetd
или dropbear
) закрывает главную сторону pty:
- как правило,
bash
получаетSIGHUP
и сразу же убивает фоновые задания (как и ожидалось) и завершает; - но иногда,
bash
обнаруживаетEOF
на рабской стороне pty до обращениеSIGHUP
.
, когда bash
обнаруживает EOF
, он по умолчанию завершается немедленно без отправки SIGHUP
. И фоновая работа остается запущенной!
решение
можно настроить bash
отправить SIGHUP
при нормальном выходе (включая EOF
) тоже:
-
обеспечить
bash
как войти shell. Thehuponexit
работает только для оболочек входа, AFAIK.оболочка входа включена или ведущий дефис на
argv[0]
. Вы можете настроитьtelnetd
для выполнения/bin/bash -l
или лучше/bin/login
вызывает/bin/sh
в оболочку режим.например:
telnetd -l /bin/login
-
включить .
например:
shopt -s huponexit
типа этого
bash
сеанс каждый раз или добавить его в.bashrc
или/etc/profile
.
почему гонка происходит?
bash
разблокирует сигналы только тогда, когда это безопасно, и блокирует их, когда некоторая часть кода не может быть безопасно прервана обработчиком сигнала.
такие критические секции invoke точки прерывания время от времени, и если сигнал получен при выполнении критического раздела, его обработчик задерживается до следующей точки прерывания или выхода критического раздела.
вы можете начать копать от quit.h
в исходном коде.
таким образом, кажется, что в нашем случае bash
иногда получает SIGHUP
, когда он находится в критической секции. SIGHUP
обработчик исполнение откладывается, и bash
читает EOF
и заканчивается до выход из критической секции или позвонив следующей точки прерывания.
ссылка
- "Управление Заданиями" раздел в официальном руководстве Glibc.
- Глава 34 "группы процессов, сеансы и управление заданиями" книги "интерфейс программирования Linux".
для того, чтобы полностью понять, что происходит, вам нужно попасть в unix
ВКУ немного.
когда вы используете команду
./app_name &
на app_name
отправляется в фоновую группу процессов. Вы можете проверить о unix
обработка группы здесь
когда вы закрываете bash
при нормальном выходе он срабатывает SIGHUP
сигнал зависания для всех своих заданий. Некоторая информация о unix
Контрольная работа здесь.
для того, чтобы сохранить ваше приложение работает при выходе bash
вам нужно сделать ваше приложение иммунным к сигналу зависания с nohup
утилиты.
nohup-запустите команду, невосприимчивую к зависаниям, с выходом в non-tty
и, наконец, это то, как вам нужно это сделать.
nohup app_name & 2> /dev/null;
когда вы закрываете терминал, shell отправляет SIGHUP
для всех фоновых процессов – и это их убивает. Это можно подавить несколькими способами, в частности:
nohup
при запуске программы с nohup
он ловит SIGHUP
и перенаправление вывода программы.
$ nohup app &
открестился
disown
говорит shell не отправлять SIGHUP
$ app &
$ disown
зависит ли это от версии linux?
это зависит от вашей оболочки. Выше применяется по крайней мере для Баш.
AFAIK в обоих случаях процесс должен быть убит. Чтобы избежать этого, вы должны выпустить nohup следующим образом:
> nohup ./my_app &
таким образом, ваш процесс будет продолжать выполняться. Вероятно, часть telnet связана с ошибкой, подобной этой: