В соответствии с Расширенным программированием Стивенса в среде UNIX глава 13, это процедура для создания демона Unix с хорошим поведением:
- Вилка и родительский выход. Это заставляет оболочку или загрузочный скрипт думать, что команда выполнена. Кроме того, дочерний процесс гарантированно не будет лидером группы процессов (обязательным условием для setsid затем)
- Позвоните
setsid
, чтобы создать новый сеанс. Это делает три вещи:
- Процесс становится лидером сеанса нового сеанса
- Процесс становится лидером группы процессов новой группы процессов
- Процесс не имеет управляющего терминала
- При желании снова раскошелиться и получить родительский выход. Это гарантирует, что демон не является лидером сеанса и не может получить управляющий терминал (в соответствии с SVR4)
- Измените текущий рабочий каталог на
/
, чтобы не мешать подключению и отключению
- Установите маску создания режима файла равной 000, чтобы разрешить создание файлов с любым необходимым разрешением позже.
- Закрыть ненужные файловые дескрипторы, унаследованные от родительского (в любом случае управляющего терминала нет):
stdout
, stderr
и stdin
.
В настоящее время существует файл для отслеживания PID, который активно используется сценариями загрузки дистрибутива Linux. Обязательно запишите PID внука, либо возвращаемое значение второго форка (шаг 3), либо значение getpid()
после шага 3.
Вот реализация Ruby, в основном переведенная из книги, но с двойным форком и записывающая PID демона.
# Example double-forking Unix daemon initializer.
raise 'Must run as root' if Process.euid != 0
raise 'First fork failed' if (pid = fork) == -1
exit unless pid.nil?
Process.setsid
raise 'Second fork failed' if (pid = fork) == -1
exit unless pid.nil?
puts "Daemon pid: #{Process.pid}" # Or save it somewhere, etc.
Dir.chdir '/'
File.umask 0000
STDIN.reopen '/dev/null'
STDOUT.reopen '/dev/null', 'a'
STDERR.reopen STDOUT