Подтвердить что ты не робот

Создание демона с двойной вилкой в ​​Ruby

Каков правильный способ создания хорошо зарекомендовавшего себя Unix или Linux-демона в Ruby?

Каково определение хорошо зарекомендовавшего себя демона и как написать такую ​​программу в Ruby?

4b9b3361

Ответ 1

В соответствии с расширенным программированием Stevens в главе 13 UNIX Environment, это процедура создания хорошего демона Unix:

  • Вилка и родительский выход. Это означает, что оболочка или boot script считают, что команда выполнена. Кроме того, дочерний процесс гарантированно не является лидером группы процессов (предварительное условие для setid next)
  • Вызовите 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