После входа через ssh
я набираю эту команду в bash
:
спать 50000000000000 &
Затем я убиваю -9
родительский процесс (сна
т. е. bash
). Затем окно терминала отключается одновременно.
Когда я снова вхожу в систему, я обнаруживаю, что процесс сна
все еще жив.
Вопрос :Почему процесс сна
может продолжаться, когда я выхожу из системы, а терминал закрыт? На мой взгляд, все, кроме демонов и программ nohup
, будет уничтожено при выходе из системы. Если sleep
может выжить таким образом, значит ли это, что я могу использовать этот метод вместо команды nohup
?
&
запускает процесс в фоновом режиме. Если вы наберете ps -ef
, вы увидите, что идентификатор родительского процесса (PPID )вашего сна — это ваш bash. Затем выйдите из системы и войдите снова. Процесс продолжит работу после выхода из системы. После входа во второй раз вы снова запускаете ps -ef
. Вы увидите, что теперь родителем вашего спящего процесса будет процесс с идентификатором «1». Это init, родитель всех процессов.
Использование &
заставит программу работать в фоновом режиме. Чтобы увидеть программу в фоновом режиме, используйте команду bg
, а чтобы снова запустить ее на переднем плане, запустите fg
.
Да, есть много способов сохранить работу программы даже при выходе из главного терминала.
Почему процесс
сна
может продолжаться, когда я выхожу из системы, а терминал закрыт? На мой взгляд, все, кроме демонов и программnohup
, будет уничтожено при выходе из системы. Еслиsleep
может выжить таким образом, значит ли это, что я могу использовать этот метод вместо командыnohup
?
Если экземпляр bash
, порожденный ssh
, не имеет установленной опции huponexit
, ни один процесс не будет завершен каким-либо образом при выходе/выходе из системы, и когда ] установлена опция huponexit
, использование kill -9
в оболочке не является хорошей альтернативой использованию nohup
в дочерних процессах оболочки; nohup
для дочерних процессов оболочки по-прежнему будет защищать их от сообщений SIGHUP, исходящих не от оболочки, и даже если это не важно, nohup
по-прежнему предпочтительнее, поскольку позволяет оболочке завершился изящно.
В bash
есть опция, называемая huponexit
, которая, если установлена, заставит bash
SIGHUP своих дочерних элементов при выходе / выходе из системы;
В интерактивном не -логин экземпляры bash
, такие как экземпляр bash
, порожденный терминалом gnome -
, этот параметр игнорируется; установлен ли huponexit
или нет, bash
дочерние элементы никогда не будут получать SIGHUP от bash
при выходе;
В интерактивном логин экземпляров bash
, например, в экземпляре bash
, порожденном ssh
, эта опция не игнорируется (, однако по умолчанию она не установлена ); если huponexit
установлен, bash
дочерние элементы будут получать SIGHUP от bash
при выходе / выходе из системы; если huponexit
не установлен, bash
дочерние элементы не будут получать SIGHUP от bash
при выходе / выходе из системы;
Таким образом, в целом выход/выход из интерактивного экземпляра login bash
, если не установлена опция huponexit
, не сделает оболочку SIGHUP своими дочерними элементами, а выход/выход из интерактивный экземпляр non -login bash
не будет делать SIGHUP оболочкой своими дочерними элементами независимо;
Это, однако, в данном случае не имеет значения :использование kill -9
sleep
выживет в любом случае, потому что его родительский процесс будет уничтожен (баш
)не оставит шанса последнему сделать что-либо первому (т. е., например, если текущий экземпляр 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
), которые позволяют ему выйти изящно.
Если
сон
может выжить таким образом, если это означает, что я могу использовать это вместо командыnohup
?
kill -9
— это действительно не тот путь, по которому следует идти. Это как стрелять из пистолета в телевизор, чтобы его выключить. Кроме комедийной составляющей плюсов нет. Процессы не могут перехватывать или игнорировать SIGKILL
. Если вы не дадите процессу возможность завершить то, что он делает, и очистить его, он может оставить поврежденные файлы (или другое состояние )и не сможет запуститься снова. kill -9
это последняя надежда, когда больше ничего не работает.
Почему процесс сна может выжить, когда я выхожу из системы, а терминал закрыт. В на мой взгляд, все, кроме демона и программы nohup, будет убито при выходе из системы.
Что происходит в вашем случае :
Родительским процессом sleep
является запущенная в данный момент оболочка bash
. Когда вы убиваете -9
этот bash, процесс bash не имеет возможности отправить SIGHUP
любому из своих дочерних процессов, потому что SIGKILL
(который посылает kill -9
)не улавливается процессом. Процесс сна продолжает работать. теперь сон стал сиротским процессом .
Процесс init (PID 1 )реализует механизм, называемый переподчинением. Это означает, что процесс инициализации теперь становится родителем этого осиротевшего процесса. init является исключением, процессы могут стать его дочерними, поскольку он собирает процессы, которые потеряли свой исходный родительский процесс. Кстати :Демон (вроде sshd
)делает это, когда «идет в фоновом режиме».
Если бы этого не произошло, осиротевший процесс позже (по завершении )стал бы процессом-зомби. Вот что происходит, когда waitpid ()
не называется (ответственностью родительского процесса, которая не может быть выполнена, когда этот процесс был убит ). init вызывает ожиданиеpid ()
в определенный интервал, чтобы избежать детей-зомби.
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 и вышел в соответствии с запросом.
Здесь могут быть задействованы два вида 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
от драйвера терминала (a sigaction
-зарегистрированный обработчик сигнала будет читать pid отправителя как si_pid==0
).
Во-вторых, SIGHUP
отправляется оболочкой в зависимости от ее настроек (si_pid!=0
).. Интерактивный bash повторно отправляет полученные SIGHUP
всем своим заданиям переднего плана. Такое поведение позволяет вам иметь несколько интерактивных bash друг над другом (, как если бы вы запускали bash
из bash для входа и, возможно, некоторых экземпляров bash (без &
в конце )из него )и будьте уверены, что SIGHUP
из первого (управляющего )bash будет отправлен вниз, даже если каждый управляющий bash создаст свою собственную группу процессов, и поэтому SIGHUP
, отправленный драйвером терминала, не сможет достичь потомки. (Это есть не во всех оболочках. Например, у Dash нет. )Bash также будет повторно отправлять SIGHUP
своим фоновым процессам, но только если параметр huponexit
включен и задание не disown
изменено. Ни одна из этих повторных отправок не может быть применена, если оболочка была принудительно убита SIGKILL
(kill -9
).
Изменить :
Только что нашел очень актуальный ответ https://stackoverflow.com/a/32786211/1084774от gavv , в котором есть еще пара деталей.