如何将Ruby程序变成守护进程?

26

我想编写一个Ruby程序,它将一直在我的Mac后台运行(也就是一个守护进程)。

有没有人可以指导我如何做到这一点?

5个回答

28

现在的Ruby 1.9.x版本具有以下功能:

Process.daemon

把它放到你的代码中,就这样。

摘自"在Ruby中使用守护进程"。


18

这可能是个愚蠢的问题,但 daemonize.rb 文件在哪里?它是一个 gem 吗?我能在网上找到它吗?它是否属于标准库?亦或是其他什么? - ab217
这是一个宝石。你只需要安装并开始使用它。 - zengr
2
如果应用程序关闭了,守护进程是否仍然会运行? - lesce

4

很高兴你觉得这很有帮助!我个人喜欢launchd...因为它可以在进程意外死亡时重新启动它。 - fitzgeraldsteele

3

需要查看针对Rails 3的daemons-rails gem(基于rails_generator):

https://github.com/mirasrael/daemons-rails

可以像这样生成daemon stub:

rails generate daemon <name>

特性:

  • 每个守护进程有独立的控制脚本
  • 每个守护进程都有 rake:daemon 命令
  • 支持 capistrano
  • 应用程序范围内的控制脚本
  • 监控 API
  • 支持多个守护进程集合

3
这是一个模块,可以将您的代码变成守护进程。这里有一个分支,可以包装现有的脚本。
基本上,它可以归结为以下内容(来自Travis Whitton的Daemonize.rb,第一个链接,修改了一些我很久以前写的程序):
private
# This method causes the current running process to become a daemon
# If closefd is true, all existing file descriptors are closed
def daemonize(pathStdErr, oldmode=0, closefd=false)
    srand # Split rand streams between spawning and daemonized process
    safefork and exit# Fork and exit from the parent

    # Detach from the controlling terminal
    unless sess_id = Process.setsid
        raise 'Cannot detach from controlled terminal'
    end

    # Prevent the possibility of acquiring a controlling terminal
    if oldmode.zero?
        trap 'SIGHUP', 'IGNORE'
        exit if pid = safefork
    end

    Dir.chdir "/"   # Release old working directory
    File.umask 0000 # Insure sensible umask

    if closefd
        # Make sure all file descriptors are closed
        ObjectSpace.each_object(IO) do |io|
            unless [STDIN, STDOUT, STDERR].include?(io)
                io.close rescue nil
            end
        end
    end

    STDIN.reopen "/dev/null"       # Free file descriptors and
    STDOUT.reopen "/dev/null"   # point them somewhere sensible
    STDERR.reopen pathStdErr, "w"           # STDOUT/STDERR should go to a logfile
    return oldmode ? sess_id : 0   # Return value is mostly irrelevant
end

# Try to fork if at all possible retrying every 5 sec if the
# maximum process limit for the system has been reached
def safefork
    tryagain = true
    while tryagain
        tryagain = false
        begin
            if pid = fork
                return pid
            end
        rescue Errno::EWOULDBLOCK
            sleep 5
            tryagain = true
        end
    end
end

Mark,虽然这是更多普通Unix系统的正确代码,并且在Mac OS X上它基本可以工作,但这真的不是正确的步骤...我没有一个现成的配方可以轻松地使用launchd注册Ruby脚本,但这可能是该帖子作者应该寻找的。 :-) - Kaelin Colclasure
@Kaelin,非常好的观点。我应该更仔细地阅读问题。不幸的是,我对苹果电脑一无所知... - Mark
很好的解释。 - z atef

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接