%3F%20%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA%20%D0%B2%20%D1%84%D0%BE%D0%BD%D0%BE%D0%B2%D0%BE%D0%BC%20%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B5.png)
Какие шаги нужно сделать, чтобы процесс отсоединился от терминала? Для этого я нашел страницу руководстваdaemon()
В описании они упомянули
Если nochdir равен нулю, daemon() изменяет текущий рабочий каталог процесса на корневой каталог ("/"); в противном случае текущий рабочий каталог остается неизменным.
Если noclose равен нулю, daemon() перенаправляет стандартный ввод, стандартный вывод и стандартную ошибку в /dev/null; в противном случае никакие изменения в эти файловые дескрипторы не вносятся.
На самом деле, я пытался заставить свой код Python работать как демон. Я нашел tcollector
кодздесь. В этом коде они также следуют тем же шагам, что и в описании daemon()
. Поэтому мой вопрос в том, почему мы должны делать эти шаги (по сравнению сdaemonize()
в tcollector
) нравится
зачем менять dir
на /
, umask
на 022
, а затем звонить os.setsid()
и т. д.
решение1
На самом деле там больше информации, чем вы процитировали, но я думаю, что эта страница руководства могла бы быть более понятной.
Если nochdir равен нулю,
daemon()
изменяет текущий рабочий каталог процесса на корневой каталог (/
)
Здесь предполагается, что программа запускается из командной строки администратора, и идея состоит в том, чтобы отсоединить демон от того, что администратор делал в это время. Изменение рабочего каталога на /
не позволяет демону держать точку монтирования занятой. Например, если рабочий каталог был /home/admin
и некоторое время спустя вы хотите размонтировать /home
, демон предотвратит это.
Если noclose равен нулю,
daemon()
перенаправляет стандартный ввод, стандартный вывод и стандартную ошибку в/dev/null
;
Это сделано для того, чтобы демон не сбивал с толку пользователей, записывая случайные сообщения об ошибках или что-то подобное на их терминал. Что демон, вероятно, должен сделать, так это открыть какой-нибудь (настроенный) файл журнала и записать туда все, что он хочет сообщить наружу.
(Эта функция разветвляется, и если fork(2) завершается успешно, родитель вызывает _exit(2), так что дальнейшие ошибки видны только потомку.)
Опять же, чтобы отключиться от сеанса оболочки администратора, основная программа немедленно возвращается, а другая часть остается в фоновом режиме, поэтому нет необходимости явно запрашивать запуск программы в фоновом режиме (например, ./daemon &
)
Теперь то, о чем страница руководства явно не говорит, но подразумевает здесь (в разделе ОШИБКИ):
Реализация этой функции в библиотеке GNU C была взята из BSD и не использует технику двойного ветвления (т. е. fork(2), setsid(2), fork(2)), необходимую для того, чтобы гарантировать, что полученный процесс-демон не является лидером сеанса. Вместо этого полученный демон является лидером сеанса.
daemon()
также звонкиsetsid()
освободить себя от сеансауправляющий терминал, и, следовательно, из сигналов, посылаемых терминалом. Но как говорится в цитате, это оставляет возможность того, что если он открывает терминальное устройство, он может случайно получить его в качестве управляющего терминала вместо этого. Чтобы избежать этого, некоторые программы вызывают fork()
, затем setsid()
из дочернего процесса, а затем снова разветвляются, выходя из обоих родителей, так что полученный процесс не является лидером сеанса (средний является/был), и не может получить управляющий терминал. Программа Python, на которую вы ссылаетесь, делает именно это.
Изменение umask
не похоже на то, чтобы быть связанным с демонизацией. Возможно, эта программа имеет особую потребность в этом.