Почему мой процесс продолжает работать после выхода из системы?

Почему мой процесс продолжает работать после выхода из системы?

После входа в систему через ssh, я ввожу следующую команду bash:

sleep 50000000000000 &

Затем я запускаю kill -9родительский sleepпроцесс процесса (т.е. bash). Затем одновременно отключается окно терминала.

Когда я снова вхожу в систему, я обнаруживаю, что sleepпроцесс все еще активен.

Вопрос: Почему sleepпроцесс может выжить, когда я выхожу из системы и терминал закрывается? По-моему, все, кроме демонов и nohupпрограмм, будет убито во время выхода из системы. Если sleepможет выжить таким образом, значит ли это, что я могу использовать этот метод вместо команды nohup?

решение1

Tl;dr:

Почему sleepпроцесс может выжить, когда я выхожу из системы и терминал закрывается? По-моему, все, кроме демонов и nohupпрограмм, будет убито во время выхода из системы. Если sleepможет выжить таким образом, значит ли это, что я могу использовать этот метод вместо команды nohup?

Если bashу порожденного экземпляра sshне установлен этот huponexitпараметр, ни один процесс не будет завершен каким-либо образом при выходе из системы или выходе из нее, а если этот huponexitпараметр установлен, использование kill -9в оболочке не является хорошей альтернативой использованию nohupв дочерних процессах оболочки; nohupиспользование в дочерних процессах оболочки по-прежнему защитит их от сигналов SIGHUP, исходящих не от оболочки, и даже если это не важно, nohupвсе равно является предпочтительным, поскольку позволяет корректно завершить оболочку.


В bashесть опция huponexit, которая, если установлена, будет заставлять bashсвои дочерние элементы SIGHUP при выходе/выходе из системы;

В интерактивном режимене-логин bashэкземпляры, например, в bashэкземпляре, порожденном gnome-terminal, этот параметр игнорируется; независимо от того, huponexitустановлен он или нет, bashдочерние элементы никогда не будут SIGHUP-ом bashпри выходе;

В интерактивном режимеавторизоваться bashэкземпляры, например, в bashэкземпляре, порожденном ssh, этот параметр не игнорируется (однако по умолчанию он не установлен); если huponexitустановлен, то bashдочерние элементы будут SIGHUPped bashпри выходе/выходе из системы; если huponexitне установлен, bashто дочерние элементы не будут SIGHUPped bashпри выходе/выходе из системы;

Таким образом, в общем случае выход из интерактивного экземпляра входа/выход из него bash, если не huponexitустановлен этот параметр, не заставит оболочку выполнить SIGHUP для своих дочерних элементов, а выход из интерактивного bashэкземпляра без входа/выход из него не заставит оболочку выполнить SIGHUP для своих дочерних элементов независимо от этого;

Однако в данном случае это не имеет значения: using kill -9 sleepбудет существовать в любом случае, поскольку завершение его родительского процесса ( bash) не оставит последнему возможности сделать это.что-либок первому (т.е., например, если текущий bashэкземпляр был экземпляром входа bashи huponexitбыла установлена ​​опция, SIGHUP для него).

В дополнение к этому, в отличие от других сигналов (например, сигнала SIGHUP, отправляемого bash), сигнал SIGKILL никогда не распространяется на дочерние процессы процесса, поэтому sleepон даже не завершается;

nohupзапускает процесс, невосприимчивый к сигналам SIGHUP, что является чем-то другим; это предотвратит зависание процесса при получении сигнала SIGHUP, который в этом случае мог быть получен экземпляром интерактивного входа в систему, bashесли huponexitпараметр был установлен, а оболочка вышла; таким образом, технически использование nohupдля запуска процесса в bashэкземпляре интерактивного входа с huponexitнеустановленным параметром предотвратит зависание процесса при получении сигнала SIGHUP, но выход из оболочки или выход из нее не вызовет SIGHUP в любом случае;

Однако в целом, когда nohupнеобходимо предотвратить поступление сигналов SIGHUP из родительской оболочки, нет причин предпочитать kill -9метод родительской оболочки nohupметоду дочерней оболочки; вместо этого должно быть наоборот.

Уничтожение родителя с помощью kill -9метода не оставляет родителю возможности корректно завершить работу, в то время как запуск дочернего процесса с помощью nohupметода позволяет завершить родителя другими сигналами, такими как SIGHUP (чтобы привести пример, который имеет смысл в контексте дочернего процесса, запущенного с помощью nohup), что позволяет ему корректно завершить работу.

решение2

bashпо умолчаниюне отправляет сигнал HUP дочерним процессам при выходе. Подробнее (спасибо @kos), он никогда этого не делаетоболочки без входа в систему.

Вы можете настроить bash так, чтобы он делал этооболочки входаесли установлена ​​опция huponexit. В терминале выполните:

[romano:~] % bash -l

(это запустит новую оболочку «входа»)

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

Теперь проверьте sleepпроцесс:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

...не запущен: получил сигнал HUP и завершил работу по запросу.

решение3

Если sleepя смогу выжить таким образом, значит ли это, что я смогу использовать этот метод вместо nohupкоманды?

kill -9на самом деле не тот путь, по которому следует идти. Это как стрелять из пистолета в телевизор, чтобы выключить его. Кроме комического компонента, никаких преимуществ нет. Процессы не могут поймать или проигнорировать SIGKILL. Если вы не дадите процессу шанса закончить то, что он делает, и очиститься, он может оставить поврежденные файлы (или другое состояние) и не сможет начать снова. kill -9это последняя надежда, когда ничего не работает.


Почему процесс сна может выжить, когда я выхожу из системы и терминал закрыт. По-моему, все, кроме демона и программы nohup, будет убито при выходе из системы.

Что происходит в вашем случае:

Родительский процесс sleep— это запущенная в данный момент bashоболочка. Когда вы kill -9используете bash, процесс bash не имеет возможности отправить SIGHUPни одному из своих дочерних процессов, поскольку SIGKILL(который отправляется kill -9) не может быть перехвачен процессом. Процесс sleep продолжает работать. sleep теперь сталсиротский процесс.

Процесс init (PID 1) использует механизм, называемый переподчинением. Это означает, что процесс init теперь становится родителем этого осиротевшего процесса. init — исключение, процессы могут стать его дочерними, поскольку он собирает процессы, которые потеряли свой исходный родительский процесс. Кстати: демон (вроде sshd) делает это, когда «переходит в фоновый режим».

Если бы этого не произошло, осиротевший процесс позже (после завершения) стал бы процессом-зомби. Это то, что происходит, когда waitpid()не вызывается (ответственность родительского процесса, которая не может быть выполнена, когда этот процесс был убит). init вызывается waitpid()в определенном интервале, чтобы избежать дочерних процессов-зомби.

решение4

Использование &заставит программу работать в фоновом режиме. Чтобы увидеть программу в фоновом режиме, используйте bgкоманду , а чтобы снова запустить ее в фоновом режиме, запустите fg.

Да, есть много способов продолжить работу программы даже при выходе из главного терминала.

Связанный контент