После входа в систему через 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
.
Да, есть много способов продолжить работу программы даже при выходе из главного терминала.