Зачем использовать os.setsid() в Python?
Я знаю, что os.setsid () должен изменить идентификатор группы процесса (разветвленный) на себя, но зачем нам это нужно?
Я вижу ответ от Google: сохранить дочерний процесс во время выхода из родительского процесса.
Но согласно моему тесту, приведенному ниже, без os.setsid () дочерний процесс также не завершится, даже если родительский процесс завершится (или будет уничтожен). Так почему же нам нужно добавить os.setsid ()? Благодарю.
import os
import time
import sys
mainPid = os.getpid()
print("Main Pid: %s" % mainPid)
pid = os.fork()
if pid > 0:
time.sleep(3)
print("Main process quit")
sys.exit(0)
#os.setsid()
for x in range(1, 10):
print("spid: %s, ppid: %s pgid: %s" % (os.getpid(), os.getppid(), os.getpgid(0)))
time.sleep(1)
1 ответ
Призвание setsid
обычно это один из этапов, через которые проходит процесс, становясь так называемым процессом-демоном. (Речь идет о Linux/Unix OS).
С setsid
разрыв связи с управляющим терминалом. Это означает, что процесс НЕ будет затронут выходом из системы.
Есть и другой способ выжить при выходе из системы, но цель этого "демонизирующего" процесса - создать фоновый процесс, максимально независимый от внешнего мира.
Вот почему все унаследованные дескрипторы закрыты; cwd настроен на соответствующий каталог, часто корневой каталог; и процесс покидает сеанс, с которого он был запущен.
Двойной fork
подход обычно рекомендуется. На каждом fork
родитель выходит, а ребенок продолжает. На самом деле ничего не меняется, кроме PID, но это именно то, что нужно здесь.
Первый fork
перед setsid
удостоверяется, что процесс не является лидером группы процессов. Что требуется для успешного setsid
,
Второй fork
после setsid
гарантирует, что новая ассоциация с управляющим терминалом не будет запущена простым открытием оконечного устройства.
ПРИМЕЧАНИЕ: когда процесс демона запускается из systemd
, systemd
Можно организовать все, что описано выше, поэтому процесс не должен.
В некоторых случаях дочерний процесс сможет продолжить работу даже после выхода из родительского, но это не является надежным. Потомок также будет выходить, когда родитель выходит в некоторых ситуациях.
Начиная с Python 3.2, вы можете использовать subprocess.Popen() и передать start_new_session=True, чтобы полностью отделить дочерний процесс от родительского.
В документах говорится:
Если start_new_session истинно, системный вызов setsid() будет выполнен в дочернем процессе до выполнения подпроцесса. (Только POSIX)
Ну, двойной форк для демонизации - хороший пример. Однако лучше понять, что такое группа процессов и сессия.
- Идентификатор сеанса (SID)
Это просто PID лидера сеанса. Если PID == SID, то этот процесс является лидером сеанса.
Сеансы и группы процессов - это просто способы рассматривать несколько связанных процессов как единое целое. Все члены группы процессов всегда принадлежат к одному сеансу, но в сеансе может быть несколько групп процессов.
Обычно оболочка является лидером сеанса, и каждый конвейер, выполняемый этой оболочкой, будет группой процессов. Это сделано для того, чтобы упростить убийство дочерних элементов оболочки при ее выходе. (См. Подробности на выходе (3).)
Обычно, если вы входите в систему, ваша оболочка запускает сеанс. Если вы хотите, чтобы ваш процесс работал даже после выхода из системы, вам следует начать новый сеанс для ребенка.
Разница с double fork
ed заключается в том, что вы все еще можете подключить к этому процессу управляющий терминал, поскольку он является лидером сеанса, тогда как процесс-демон, созданный double fork
больше не может быть прикреплен к терминалу.