【问题标题】:Starting and Stopping Ruby Daemons启动和停止 Ruby 守护进程
【发布时间】:2012-09-05 00:21:13
【问题描述】:

我正在尝试使用 daemons gem 启动和停止无限循环守护程序。

看着home page,我试过(在irb中):

require 'daemons'
=>true
task_handle = Daemons.call do
  loop{
    sleep 10
    puts "foo"
  }
end
=> #<Daemons::Application:0x000000043f96d0 ...
task_handle.stop
=> nil
task_handle2 = Daemons.call do
  loop{
    sleep 10
    puts "bar"
  }
end

=>Daemons::RuntimeException: there is already one or more instance(s) of the program running
from /home/bdares/.rvm/gems/ruby-1.9.3-p194/gems/daemons-1.1.9/lib/daemons/application_group.rb:125:in `new_application'
from /home/bdares/.rvm/gems/ruby-1.9.3-p194/gems/daemons-1.1.9/lib/daemons.rb:251:in `call'
from (irb):21

现在,我正在查看的确切示例(链接页面上的#3)使用选项:multiple =&gt; true 进行第一次调用,但我真的只需要一次运行一个守护程序(并且多个守护程序会,实际上是不可取的)。

第一个守护进程是否还活着并且没有被 GC 处理?如果是这样,我错过了什么?

【问题讨论】:

  • 请记住,Daemon 只是 UNIX 守护进程的抽象,它只是另一个 UNIX 进程(通常由fork() 创建,后跟daemonize())。所以 GC 对另一个 UNIX 进程实际上没有任何控制权。

标签: ruby daemons


【解决方案1】:

我认为这里的误解是守护进程没有按顺序运行。根据它们的性质,它们并行运行,它们之间几乎没有协调。我相信您可以找到 System V IPC 信号量的 Ruby 接口来协调它们,但是如果您想要一个作业队列,请查看除守护程序之外的其他东西。

此外,要添加到上面@Sigurd 的答案,这里是实现:force 选项的相关代码(方便地未记录)(source):

115: if @applications.size > 0 and not @multiple
116:         if options[:force]
117:           @applications.delete_if {|a|
118:             unless a.running?
119:               a.zap
120:               true
121:             end
122:           }
123:         end
124:         
125:         raise RuntimeException.new('there is already one or more instance(s) of the program running') unless @applications.empty?
126:       end

所以基本上,(zap,正如我在源代码中发现的那样,绝对没有),当您指定 :force,如果未设置多个。否则,您会收到错误消息。所以这意味着,如果你不指定:force:multiple,你就只会出错。

注意:所有这一切的原因是Application#stop 没有从ApplicationGroup(负责创建新工作)中删除守护进程。

注意:顺便说一下,在 Ruby 中使用{} 表示多行块是一种不好的形式。仅对单行块使用{}。使用do...end 代替多行。

【讨论】:

    【解决方案2】:

    以下代码可以正常工作:

    require 'daemons'
    task_handle = Daemons.call(:force => true)  do
      loop{
        sleep 10
        puts "foo"
      }
    end
    
    task_handle.stop
    
    task_handle2 = Daemons.call do
      loop{
        sleep 10
        puts "foo"
      }
    end
    

    更改是在第一次调用:force 选项中。守护进程检查创建的应用程序编号,而不仅仅是它们正在运行。在您的情况下,即使停止后第一个实例仍然存在。 “强制”选项会清除未运行的应用程序。

    请注意,您可能会遇到另一个问题 - task_handle.stop 不保证生成的 proc 会立即停止,因此您需要处理这种情况。

    【讨论】:

      猜你喜欢
      • 2012-01-24
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多