启动和停止Ruby守护进程

时间:2012-09-12 02:20:08

标签: ruby daemons

我正在尝试使用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 => true进行第一次调用,但我实际上只需要一个守护进程一次运行(并且多个事实上,这将是不受欢迎的。)

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

2 个答案:

答案 0 :(得分:1)

以下代码可以正常工作:

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选项中。守护进程检查已创建的应用程序编号,而不仅仅是它们正在运行。在您的情况下,即使停止后第一个实例仍然存在。 “force”选项可清除未运行的应用程序。

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

答案 1 :(得分: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时,守护进程将删除所有未运行的应用程序如果未设置多个,则@applications。否则,您会收到错误消息。那么这意味着如果你没有指定:force:multiple,那么你就会在错误的单行道上。

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

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