После входа в систему через ssh
, Я ввожу эту команду bash
:
sleep 50000000000000 &
Затем я kill -9
sleep
родительский процесс процесса (т.е. bash
). Затем окно терминала разъединяется одновременно.
Когда я вхожу в систему снова, я нахожу что sleep
процесс все еще жив.
Вопрос: Почему может sleep
процесс выживает, когда я выхожу из системы, и терминал закрывается? В моем уме, всем кроме демонов и nohup
программы будут закрыты во время выхода из системы. Если sleep
может выжить таким образом, делает это означает, что я могу использовать этот метод вместо nohup
команда?
Почему может
sleep
процесс выживает, когда я выхожу из системы, и терминал закрывается? В моем уме, всем кроме демонов иnohup
программы будут закрыты во время выхода из системы. Еслиsleep
может выжить таким образом, делает это означает, что я могу использовать этот метод вместоnohup
команда?
Если bash
экземпляр, порожденный ssh
имеет huponexit
набор опции, никакой процесс не будет завершен никем, означают на выход / выходят из системы, и когда huponexit
опция установлена, с помощью kill -9
на оболочке не хорошая альтернатива использованию nohup
на дочерних процессах оболочки; nohup
на дочерних процессах оболочки все еще защитит их от SIGHUPs, не прибывающего из оболочки, и даже когда это не важно nohup
должен все еще быть предпочтен, потому что это позволяет оболочке быть завершенной корректно.
В bash
существует названная опция huponexit
, который, если установленный сделает bash
SIGHUP его дети на выход / выход из системы;
В интерактивном невходе в систему bash
экземпляры, такой как в a bash
экземпляр, порожденный gnome-terminal
, эта опция проигнорирована; ли huponexit
установлен или сброшен, bash
дети никогда не будут SIGHUPped bash
на выход;
В интерактивном входе в систему bash
экземпляры, такой как в a bash
экземпляр, порожденный ssh
, эта опция не проигнорирована (однако, она сброшена по умолчанию); если huponexit
установлен, bash
дети будут SIGHUPped bash
на выход / выход из системы; если huponexit
сброшен, bash
дети не будут SIGHUPped 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 -9
на родительском методе к nohup
на дочернем методе; вместо этого, это должно быть противоположное.
Уничтожение родителя с помощью kill -9
метод не оставляет шанс для родителя для выхода корректно при запуске дочернего элемента, использующего nohup
метод позволяет родителю быть завершенным другими сигналами, такими как SIGHUP (для создания примера, который имеет смысл в контексте дочернего элемента, запущенного использовать nohup
), которые позволяют этому выходить корректно.
bash
по умолчанию не отправляет вниз Сигнал HUP в дочерние процессы при выходе. Больше подробно (благодарит @kos), он никогда не делает это для оболочек невхода в систему.
Можно настроить удар, чтобы сделать это для оболочек входа в систему, если установлено опция 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 и вышло согласно просьбе.
Если
sleep
может выжить таким образом, если это означает, что я могу использовать этот метод вместоnohup
команда?
kill -9
действительно не путь, которым нужно пойти. Это похоже на стрельбу с оружием на телевидении для выключения его. Помимо комичного компонента нет никакого преимущества. Процессы не могут поймать или проигнорировать SIGKILL
. Если Вы не даете процессу шанс закончить то, что он делает, и вымойтесь, он может оставить поврежденные файлы (или другое состояние) вокруг и не сможет запуститься снова. kill -9
последняя надежда, когда ничто иное не работает.
Почему спящий процесс может выжить, когда я выхожу из системы, и терминал закрывается. В моем уме все кроме демона и nohup программы будет уничтожено когда выход из системы.
Что в Вашем случае происходит:
Родительский процесс sleep
в настоящее время рабочий bash
оболочка. Когда Вы kill -9
тот удар, процесс удара не имеет шанса отправить a SIGHUP
к любому из его дочерних процессов, потому что SIGKILL
(который отправляется kill -9
) не catchable процессом. Спящий процесс продолжает работать. сон теперь стал процессом висячей строки.
init (PID 1), процесс делает механизм, назвал перепорождение. Это означает, что процесс init теперь становится родителем того осиротевшего процесса. init является исключением, процессы могут стать, это - ребенок, поскольку это собирает процессы, которые потеряли их исходный родительский процесс. Btw: демон (как sshd
) делает это, "идя в фоновом режиме".
Если бы этого не произошло бы, осиротевший процесс позже (по окончании) стал бы процессом-зомби. Это - то, что происходит когда waitpid()
не назван (ответственность родительского процесса, который не может быть выполнен когда, когда тот процесс был уничтожен). вызовы init waitpid()
в определенном интервале для ухода от зомби childs.
&
запуски процесс в фоне. Если Вы тип ps -ef
, Вы будете видеть, что родительский ID процесса (PPID) Вашего сна является Вашим ударом. Тогда выход из системы и логин снова. Процесс останется бежать за Вами выход из системы. После того, как Вы войдете в систему во второй раз, когда Вы бежите ps -ef
снова. Вы будете видеть, что теперь родитель Вашего процесса сна будет процессом с id «1». Это - init, родитель всех процессов.
Используя &
заставит программу бежать как фон. Видеть, что программа на заднем плане использует bg
команда и делает его бегущий как передний план снова, пробег fg
.
Да, есть много способов поддерживать программу в рабочем состоянии даже главный терминал, из которого выходят.
Здесь могут быть задействованы два вида SIGHUP
.
Во-первых, потому что в такой ситуации оболочка будет так называемым контролирующим процессом (оболочка лидера сеанса, владеющая управляющим терминалом — псевдотерминалом, созданным при входе в систему ssh), драйвер терминала будет обязан отправить SIGHUP
всем членам группы процессов переднего плана терминала, когда терминал отключен.
(Он также будет отправлять SIGHUP
+SIGCONT
остановленным фоновым процессам (группам потерянных процессов)).
Вы исключили такую системную отправку SIGHUP
путем фонового процесса, находясь в интерактивной оболочке. Такая фоновая обработка поместит процесс(ы) в отдельную группу процессов, которая не будет группой процессов переднего плана терминала, и поэтому драйвер не будет отправлять SIGHUP
таким процессам.
Фоновый фон сам по себе не проблема, но вам нужно запустить фон из неинтерактивной оболочки (интерактивные оболочки помещают фоновые процессы в отдельные группы процессов) и часть группы процессов переднего плана:
#from a ssh login shell
bash -c 'echo $$; sleep 1000 & sleep 1000 && wait'
#a backgrounded and a nonbackgrounded sleep, both in the foreground process group
Теперь, если бы вы kill -9
эхо-сообщение pid оболочки с другого терминала, оба спящих процесса получат SIGHUP
от драйвера терминала (обработчик сигнала, зарегистрированный в sigaction
, будет считывать pid как si_pid==0
).
Во-вторых, это SIGHUP
, отправляемые оболочкой в зависимости от ее настроек (si_pid!=0
). Интерактивный bash повторно отправляет полученные SIGHUP
всем своим заданиям переднего плана.
Такое поведение позволяет вам иметь несколько интерактивных bash друг над другом (например, если вы запускаете bash
из bash для входа и, возможно, из некоторых экземпляров bash (без &
в конце) от него)
и будьте уверены, что SIGHUP
из первого (управляющего) bash будет отправлен, даже если каждый управляющий bash создаст свою собственную группу процессов, и поэтому SIGHUP
, отправленный драйвером терминала, не будет быть в состоянии добраться до потомков. (Это есть не во всех оболочках. Например, в Dash нет.) Bash также повторно отправляет SIGHUP
своим фоновым процессам, но только если параметр huponexit
включен, а задание не т отрекся
изд. Ни одна из этих повторных отправок не может применяться, если оболочка была принудительно уничтожена с помощью SIGKILL
(kill -9
).
Редактировать:
Только что нашел очень актуальный ответ https://stackoverflow.com/a/32786211/1084774 от gavv, в котором есть еще пара деталей.