如何用Thor(ruby)创建一个守护进程?

时间:2011-01-11 15:19:49

标签: ruby daemons thor

我想使用流行的Thor gem来创建一个守护进程的任务。我的Thor课程看起来像这样:

require 'rubygems'
require 'daemons'
require 'thor'

class CLI < Thor
  desc "start", "Startup the App"
  method_option :daemonize, :aliases => "-d", :default => false, :type => :boolean, :banner => "Run as daemon"
  def start
    run_app(options[:daemonize])
  end

  desc "stop", "Stop the daemon"
  def stop
    stop_app
  end

  no_tasks {
    def run_app(run_as_daemon)
      # Run the application code
      Daemons.daemonize if run_as_daemon
      # loop until stopped or interrupted
      # ...
    end

    def stop_app
      #stop the app
    end
  }
end

所以在这里我设置了一个基本的thor类,它有两个任务,start和stop。我也是,目前正在使用Daemons gem,但这不是必需的。我正在努力的部分是,当这个应用程序以“run_thor_app.rb start”运行时,一切运行都很好。显然,在这种情况下不需要停止任务。但是当我运行“run_thor_app.rb start -d”时,应用程序会运行,直到Daemons.daemonize运行然后退出。检查正在运行的进程表明后台没有运行任何内容。

即使某些东西在运行,我也不知道如何处理停止任务。例如,如何检测应用程序作为守护程序运行并停止它。我看过Daemons :: Monitor,但文档不清楚它是如何工作的,当我尝试它时,它没有用。

在我看来,这对于内置于Thor的内容来说是一个很好的用例,但是在github上搜索代码并没有向我透露任何内容。也许我只是错过了某个地方。在任何情况下,我认为最好记录最佳实践或用Thor处理守护进程的模式以供其他人参考。

1 个答案:

答案 0 :(得分:1)

通常管理守护程序进程的方法是让它们将PID写入文件中。这使得另一个进程可以发现守护进程的PID,并将其终止(或发送一些其他信号)。

您的代码应该有效。我尝试了一个使用deamons宝石的裸骨头脚本,在我找到了deamonized进程之前我花了几次尝试。我认为它会得到与父进程相同的名称,或者类似的东西,但它的名字是“self”。请记住,守护进程将不再写入STDOUT

无论如何,试试这个:

# set up everything
# then daemonize
Daemons.daemonize
# and write a pid file
File.open('/tmp/mydaemon.pid', 'w') { |f| f.puts(Process.pid) }
loop do
  # do something
  # this loop is important, if the script ends the daemon dies
end

并检查/tmp/mydaemon.pid文件中的PID。然后运行ps ax | grep x,其中x是PID。运行cat /tmp/mydaemon.pid | xargs kill`杀死守护进程。

我认为daemons'gem有一些帮助管理PidFiles,请查看http://rubydoc.info/gems/daemons/1.1.0/frames中的PidFile