首页 文章

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

提问于
浏览
26

What is the proper way to create a well-behaved Unix or Linux daemon in Ruby?

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

2 回答

  • 6

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

    • 分叉并拥有父出口 . 这使得shell或boot脚本认为命令已完成 . 此外,保证子进程不是进程组负责人(下一个setsid的先决条件)

    • 调用 setsid 以创建新会话 . 这有三件事:

    • 该过程成为新会话的会话负责人

    • 该流程成为新流程组的流程组负责人

    • 该过程没有控制终端

    • 可选择再次fork并拥有父出口 . 这可以保证守护进程不是会话领导者,也不能获得控制终端(在SVR4下)

    • 将当前工作目录更改为 / ,以避免干扰安装和卸载

    • 将文件模式创建掩码设置为000,以允许稍后创建具有任何所需权限的文件 .

    • 关闭从父级继承的不需要的文件描述符(无论如何都没有控制终端): stdoutstderrstdin .

    现在有一个文件来跟踪由Linux分发启动脚本大量使用的PID . 务必写出孙子的PID,或者第二个叉子的返回值(步骤3)或者步骤3之后的 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
    
  • 52

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

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

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

    另一个有趣的实现是Unicorn:

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

相关问题