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

10

После входа в систему sshя набираю эту команду bash:

sleep 50000000000000 &

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

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

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

Кот
источник
3
&переведет процесс в фоновый режим (например, демон) и продолжит работу, даже если вы вышли из системы.
Айзуддин Зали

Ответы:

6

Tl; др:

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

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


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

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

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

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

Это, однако, не имеет значения в этом случае: использование 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 -9on на родительском методе методом nohupon на дочернем; вместо этого должно быть наоборот.

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

кос
источник
Другими словами, если у меня есть сценарий, который был помещен в фоновый режим, он все равно будет работать, даже если я уничтожу родительский процесс, например, моя оболочка, верно? какой способ убить этот сценарий?
Сергей Колодяжный
@Serg Если у вас есть PID, просто убейте PID; если вы не сохранили PID, но можете идентифицировать процесс по его имени, ps -e | grep processследует перечислить процесс вместе с PID (или лучше, pgrep -x processесли вы уверены, что соответствует этот единственный процесс, а не ненужные вещи); проблема в том, что когда вы убиваете процесс, когда kill -9его дочерние элементы становятся собственниками upstart, следовательно, их первоначальный PPID теряется, а их PPID изменяется на PID выскочки, что делает их неузнаваемыми (AFAIK), но для их имени или PID
kos
@kos При каких условиях невозможно nohupпредотвратить зависание процесса при получении сигнала SIGHUP от родительского процесса? Я пытаюсь запустить процесс в фоновом режиме (в терминале оболочки PuTTY SSH) nohup <command> <arg> &. Когда я выйду из системы, нажав Xкнопку PuTTY , фоновый процесс немедленно прекратится. Когда я выйду из системы, набрав exitв терминале оболочки PuTTY SSH, процесс продолжится в фоновом режиме.
userpal
3

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

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

[romano:~] % bash -l

(это запускает новую оболочку "login")

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 и вышел по запросу.

Rmano
источник
@kos --- да, вы правы , но ... так почему , если я sleep 1000 & ; exitв sleepвыживает? Обратите внимание , что если я процесс он будет выходить. И даже если установлено, выживает. Запутался ... (Я постараюсь лучше понять и изменить asnwer, иначе я его удалю). kill -HUPsleephuponexitsleep
Rmano
2

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

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


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

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

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

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

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

хаос
источник
Процесс выживает даже при вежливых сигналах, таких как TERMилиHUP
heemayl
@heemayl HUP зависит от конфигурации оболочек: huponext. И ТЕРМИН будет ждать, пока сон закончится. В случае команды сна OPs, это были бы тысячи лет =)
хаос
1

&Запускает процесс в фоновом режиме. Если вы напечатаете ps -ef, вы увидите, что ID родительского процесса (PPID) вашего сна является вашим bash. Затем выйдите и войдите снова. Процесс останется запущенным после выхода из системы. После входа в систему во второй раз вы запустите ps -efснова. Вы увидите, что теперь родитель вашего процесса сна будет обрабатываться с идентификатором "1". Это init, родитель всех процессов.

никто
источник
0

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

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

Айзуддин Зали
источник
Спасибо. man-страница bash немного сбивает с толку. В нем говорится: «Перед выходом интерактивная оболочка повторно отправляет SIGHUP всем работам, работающим или остановленным». НО на самом деле оболочка отправляет SIGHUP только во второстепенные задания. фоновые процессы не имеют возможности получить сигнал SIGHUP (если только не изменились параметры оболочки 'huponexit')
tom_cat
@kos может ты и прав. Я делаю вышеприведенный вывод из этого поста: stackoverflow.com/questions/4298741/… теперь я запутываюсь.
Tom_cat
@tom_cat Вернемся к этому еще раз, подумав дважды: просто нет случая, когда оболочка может выйти с запущенным процессом переднего плана, она может быть SIGHUPped или что-то еще, но это не выход . Так что это правильно, это относится только к фоновым процессам, потому что обратное не имеет смысла. Однако из дальнейших исследований учтите также, что это huponexitработает только для оболочек входа в систему, таких как оболочка, полученная через ssh(а не, скажем, в оболочке, полученной через gnome-terminal)
kos