Что именно определяет, будет ли фоновое задание уничтожено при выходе из оболочки или уничтожено?

12

Этот вопрос возник довольно много ( действительно много ), но я нахожу ответы, как правило, неполными. Общий вопрос: «Почему моя работа не убивается, когда я выхожу / убиваю ssh?», И вот что я нашел. Первый вопрос: насколько общая информация следующая? Кажется, что следующее верно для современного Debian linux, но я упускаю некоторые моменты; и что нужно знать другим?

  1. Все дочерние процессы, фоновые или нет оболочки, открытой через ssh-соединение, уничтожаются с помощью SIGHUP, когда ssh-соединение закрывается, только если установлена huponexitопция: запустите, shopt huponexitчтобы увидеть, правда ли это.

  2. Если huponexitэто правда, то вы можете использовать nohupили, disownчтобы отделить процесс от оболочки, чтобы он не был убит при выходе. Или запустить вещи с screen.

  3. Если задано значение huponexitfalse, которое по умолчанию используется, по крайней мере, в некоторых linux, то фоновые задания не будут уничтожены при обычном выходе из системы.

  4. Но даже если значение huponexitfalse, то, если соединение ssh будет прервано или прервано (отличается от обычного выхода из системы), фоновые процессы все равно будут прерваны. Этого можно избежать с помощью disownили nohupкак в (2).

  5. Существует некоторое различие между (a) процессами, родительский процесс которых является терминалом, и (b) процессами, к которым подключены stdin, stdout или stderr . Я не знаю, что происходит с процессами, которые (а), а не (б), или наоборот.

Последний вопрос: как я могу избежать поведения (3)? Другими словами, по умолчанию в Debian фоновые процессы проходят самостоятельно после выхода из системы, но не после разрыва соединения ssh. Я хотел бы, чтобы одно и то же происходило с процессами независимо от того, было ли соединение нормально закрыто или разорвано. Или это плохая идея?

Редактировать: Другой, важный способ сохранить рабочие места убитых, который работает (?) В любом случае, это запускать их через экран . Но вопрос больше в том, чтобы понять, когда что-то убивают, а когда нет: иногда люди хотят, чтобы рабочие места были убиты, например, при выходе из системы.

Дополнительные темы: - Разъяснение сигналов (sighup), заданий и управляющего терминала - /server/117152/do-background-processes-get-a-sighup-when-logging-off - Продолжить SSH фоновые задачи / задания при закрытии SSH - Будет ли задание, помещенное в фоновом режиме, продолжать работать после закрытия сеанса SSH? - Предотвратить остановку уже запущенного фонового процесса после закрытия клиента SSH. - Как я могу запустить процесс через SSH, чтобы он продолжал выполняться после моего отключения? - Невозможно сохранить удаленную работу на OS X - Закрыть SSH соединение

petrelharp
источник

Ответы:

1

Процесс не «убит SIGHUP» - по крайней мере, не в строгом смысле этого слова. Скорее, когда соединение разрывается, управляющему процессу терминала (в данном случае Bash) отправляется сигнал зависания *, который обычно сокращается как «сигнал HUP» или просто SIGHUP.

Теперь, когда процесс получает сигнал, он может обрабатывать его так, как хочет **. Значением по умолчанию для большинства сигналов (включая HUP) является немедленный выход. Однако программа может игнорировать сигнал или даже запускать какую-либо функцию обработчика сигнала.

Баш выбирает последний вариант. Его обработчик сигнала HUP проверяет, является ли параметр «huponexit» истинным, и, если это так, отправляет SIGHUP каждому из своих дочерних процессов. Только после того, как все закончится, Bash выйдет.

Аналогично, каждый дочерний процесс может делать все, что ему захочется, когда он получает сигнал: оставить для него значение по умолчанию (т.е. немедленно умереть), игнорировать его или запустить обработчик сигнала.

Nohup только изменяет действие по умолчанию для дочернего процесса на «игнорировать». Однако, когда дочерний процесс запущен, он может самостоятельно изменить свой ответ на сигнал.

Вот почему я думаю, что некоторые программы умирают, даже если вы запускали их с помощью nohup:

  1. Nohup устанавливает действие по умолчанию "игнорировать".
  2. При выходе из программы необходимо выполнить некоторую очистку, поэтому она устанавливает обработчик SIGHUP, случайно перезаписывая флаг «игнорировать».
  3. Когда прибывает SIGHUP, запускается обработчик, очищающий файлы данных программы (или все, что нужно было сделать) и выходит из программы.
  4. Пользователь не знает и не заботится о обработчике или очистке, а просто видит, что программа закрылась, несмотря на nohup.

Вот тут и появляется «отречься». Процесс, который был отвергнут Bash, никогда не отправляет сигнал HUP, независимо от опции huponexit. Таким образом, даже если программа устанавливает собственный обработчик сигнала, сигнал фактически никогда не отправляется, поэтому обработчик никогда не запускается. Однако обратите внимание, что если программа попытается отобразить некоторый текст для пользователя, который вышел из системы, это вызовет ошибку ввода-вывода, которая может привести к выходу программы в любом случае.

* И, да, прежде чем вы спросите, терминология "зависания" осталась со времен мэйнфреймов коммутируемого доступа UNIX.

** Большинство сигналов, так или иначе. SIGKILL, например, всегда вызывает немедленное завершение программы, точка.

HiddenWindshield
источник
2

Пункты 1-4 верны. Я ничего не знаю о пункте 5. Что касается вашего последнего пункта, хорошее приложение, экран , позволит вам позволить всем процессам работать до их естественного завершения, независимо от того, как вы прервете свое соединение. Экран в репо.

Человеческое описание экрана не легко прочитать, но, среди прочего, оно гласит:

Когда вызывается screen, он создает одно окно с оболочкой (или указанной командой), а затем исчезает, чтобы вы могли использовать программу, как обычно. Затем в любое время вы можете создавать новые (полноэкранные) окна с другими программами в них (включая другие оболочки), убивать существующие окна, просматривать список окон, включать и выключать выходной журнал, копировать и вставлять текст между окнами, просматривать историю прокрутки, переключаться между окнами любым удобным для вас способом и т. д. Все окна запускают свои программы полностью независимо друг от друга. Программы продолжают работать, когда их окно в данный момент не видно, и даже когда весь сеанс экрана отсоединен от пользовательского терминала, Когда программа завершает работу, экран (по умолчанию) убивает окно, в котором она находилась. Если это окно находилось на переднем плане, дисплей переключается на предыдущее окно; если ничего не осталось, экран выходит.

Я выделил наиболее важную часть: вы можете отсоединить окно с помощью команды Ctrl + a + d, а затем вы можете убить / выйти из сеанса, и теперь отключенное окно будет продолжать работать, а программы внутри по-прежнему будут работать. Когда вы подключаетесь обратно, например, инициируя новый сеанс ssh, команда screen -r возобновит сеанс экрана, который был отсоединен ранее, с четким отображением всех выводов в стандартную ошибку / вывод.

MariusMatutiae
источник