What is the proper way to create a well-behaved Unix or Linux daemon in Ruby?
无论如何,一个表现良好的守护进程的定义是什么,以及如何在Ruby中编写这样的程序?
根据Stevens在UNIX环境中的高级编程第13章,这是制作性能良好的Unix守护进程的过程:
分叉并拥有父出口 . 这使得shell或boot脚本认为命令已完成 . 此外,保证子进程不是进程组负责人(下一个setsid的先决条件)
调用 setsid 以创建新会话 . 这有三件事:
setsid
该过程成为新会话的会话负责人
该流程成为新流程组的流程组负责人
该过程没有控制终端
可选择再次fork并拥有父出口 . 这可以保证守护进程不是会话领导者,也不能获得控制终端(在SVR4下)
将当前工作目录更改为 / ,以避免干扰安装和卸载
/
将文件模式创建掩码设置为000,以允许稍后创建具有任何所需权限的文件 .
关闭从父级继承的不需要的文件描述符(无论如何都没有控制终端): stdout , stderr 和 stdin .
stdout
stderr
stdin
现在有一个文件来跟踪由Linux分发启动脚本大量使用的PID . 务必写出孙子的PID,或者第二个叉子的返回值(步骤3)或者步骤3之后的 getpid() 的值 .
getpid()
这是一个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
继Jason的精彩回应之后,我在这里写了一个更全面的实现:
https://gist.github.com/1372491/b76b60fb1842bf0507f47869ab19ad50a045b214
除了双叉和写入pid文件之外,我还实现了日志记录 .
另一个有趣的实现是Unicorn:
https://github.com/defunkt/unicorn/blob/master/lib/unicorn/launcher.rb
2 回答
根据Stevens在UNIX环境中的高级编程第13章,这是制作性能良好的Unix守护进程的过程:
分叉并拥有父出口 . 这使得shell或boot脚本认为命令已完成 . 此外,保证子进程不是进程组负责人(下一个setsid的先决条件)
调用
setsid
以创建新会话 . 这有三件事:该过程成为新会话的会话负责人
该流程成为新流程组的流程组负责人
该过程没有控制终端
可选择再次fork并拥有父出口 . 这可以保证守护进程不是会话领导者,也不能获得控制终端(在SVR4下)
将当前工作目录更改为
/
,以避免干扰安装和卸载将文件模式创建掩码设置为000,以允许稍后创建具有任何所需权限的文件 .
关闭从父级继承的不需要的文件描述符(无论如何都没有控制终端):
stdout
,stderr
和stdin
.现在有一个文件来跟踪由Linux分发启动脚本大量使用的PID . 务必写出孙子的PID,或者第二个叉子的返回值(步骤3)或者步骤3之后的
getpid()
的值 .这是一个Ruby实现,主要是从本书翻译而来,但是使用双叉并写出守护进程PID .
继Jason的精彩回应之后,我在这里写了一个更全面的实现:
https://gist.github.com/1372491/b76b60fb1842bf0507f47869ab19ad50a045b214
除了双叉和写入pid文件之外,我还实现了日志记录 .
另一个有趣的实现是Unicorn:
https://github.com/defunkt/unicorn/blob/master/lib/unicorn/launcher.rb