在后台运行,成为守护进程(linux)

在linux下这件事实在是太容易了。

先建个Daemon.rb

require 'fileutils'

module Daemon
  WorkingDirectory = File.expand_path(File.dirname(__FILE__))  

  class Base
    def self.pid_fn
      File.join(WorkingDirectory, "#{name}.pid")
    end
    
    def self.daemonize
      Controller.daemonize(self)
    end
  end
  
  module PidFile
    def self.store(daemon, pid)
      File.open(daemon.pid_fn, 'w') {|f| f << pid}
    end
    
    def self.recall(daemon)
      IO.read(daemon.pid_fn).to_i rescue nil
    end
  end
  
  module Controller
    def self.daemonize(daemon)
      case !ARGV.empty? && ARGV[0]
      when 'start'
        start(daemon)
      when 'stop'
        stop(daemon)
      when 'restart'
        stop(daemon)
        start(daemon)
      else
        puts "Invalid command. Please specify start, stop or restart."
        exit
      end
    end
    
    def self.start(daemon)
      fork do
        Process.setsid
        exit if fork
        PidFile.store(daemon, Process.pid)
        Dir.chdir WorkingDirectory
        File.umask 0000
        STDIN.reopen "/dev/null"
        STDOUT.reopen "/dev/null", "a"
        STDERR.reopen STDOUT
        trap("TERM") {daemon.stop; exit}
        daemon.start
      end
    end
  
    def self.stop(daemon)
      if !File.file?(daemon.pid_fn)
        puts "Pid file not found. Is the daemon started?"
        exit
      end
      pid = PidFile.recall(daemon)
      FileUtils.rm(daemon.pid_fn)
      pid && Process.kill("TERM", pid)
    end
  end
end


这是一个典型的后台进程控制类,它创建一个pid,然后使用fork产生进程,将输入输出重定向。当然也可以输出到日志文件里。

然后要做的就很简单了,先继承,然后建立一个start和stop方法,在start方法里一定要阻塞进程。在stop方法里销毁初始化的东西。

class Robot < Daemon::Base
.........
  def self.start
    init_all()
    while true
      sleep(10)
    end
  end

  def self.stop
    destory_all()
  end

.........
end


最常见的阻塞办法就是无限循环,当然了,一定要记得sleep,否则会占用100%CPU。

或者是用其他阻塞办法,反正不能结束掉。

这样使用  ruby robot.rb start 启动后就会启动一个守护进程,然后可以用ps看到守护进程活着,并且可以看到robot.rb所在目录会生成一个.pid文件,这个就是存储pid的内容。

使用 ruby robot.rb stop 关闭进程。它会发送关闭信息,同时删除pid文件。

注意在进程里使用路径一定要用绝对路径,使用相当路径是不可靠的,或者是使用本文件的相对路径,然后计算出绝对路径,例如:
  WORKING_DIRECTORY = File.expand_path(File.dirname(__FILE__))
  CONFIG_DIRECTORY=File.join(WORKING_DIRECTORY,"../config")
  XMPP_ACCOUNT_FILE=File.join(CONFIG_DIRECTORY,"xmpp_account.yml")
  DB_CONFIG_FILE=File.join(CONFIG_DIRECTORY,"database.yml")
  MSN_ACCOUNT_FILE=File.join(CONFIG_DIRECTORY,"msn_account.yml")

你可能感兴趣的:(linux,F#,Ruby)