在Ruby中使用双叉创建一个守护进程

Jas*_*ith 27 ruby unix linux fork daemon

在Ruby中创建性能良好的Unix或Linux守护进程的正确方法是什么?

无论如何,一个表现良好的守护进程的定义是什么,以及如何在Ruby中编写这样的程序?

Jas*_*ith 53

根据Stevens 在UNIX环境中高级编程第13章,这是制作性能良好的Unix守护进程的过程:

  1. 叉并且有父出口.这使得shell或boot脚本认为命令已完成.此外,保证子进程不是进程组负责人(下一个setsid的先决条件)
  2. 打电话setsid来创建一个新会话.这有三件事:
    1. 该过程成为新会话的会话负责人
    2. 该流程成为新流程组的流程组负责人
    3. 该过程没有控制终端
  3. 可选择再次fork并拥有父出口.这可以保证守护进程不是会话领导者,也不能获得控制终端(在SVR4下)
  4. 将当前工作目录更改为/以避免干扰安装和卸载
  5. 将文件模式创建掩码设置为000,以允许稍后创建具有任何所需权限的文件.
  6. 关闭不需要的文件描述符从父(没有控制终端反正)继承:stdout,stderr,和stdin.

现在有一个文件来跟踪由Linux分发启动脚本大量使用的PID.务必写出孙子的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
Run Code Online (Sandbox Code Playgroud)


小智 6

继Jason的精彩回应之后,我在这里写了一个更全面的实现:

https://gist.github.com/1372491/b76b60fb1842bf0507f47869ab19ad50a045b214

除了双叉和写入pid文件之外,我还实现了日志记录.

另一个有趣的实现是Unicorn:

https://github.com/defunkt/unicorn/blob/master/lib/unicorn/launcher.rb