require 'daemons/pid' module Daemons # === What is a Pid-File? # A Pid-File is a file containing the process identification number # (pid) that is stored in a well-defined location of the filesystem thus allowing other # programs to find out the pid of a running script. # # Daemons needs the pid of the scripts that are currently running in the background # to send them so called _signals_. Daemons uses the +TERM+ signal to tell the script # to exit when you issue a +stop+ command. # # === How does a Pid-File look like? # # Pid-Files generated by Daemons have to following format: # .rb.pid # (Note that is omitted if only one instance of the script can # run at any time) # # Each file just contains one line with the pid as string (for example 6432). # # === Where are the Pid-Files stored? # # Daemons is configurable to store the Pid-Files relative to three different locations: # 1. in a directory relative to the directory where the script (the one that is supposed to run # as a daemon) resides (:script option for :dir_mode) # 2. in a directory given by :dir (:normal option for :dir_mode) # 3. in the preconfigured directory /var/run (:system option for :dir_mode) # class PidFile < Pid attr_reader :dir, :progname, :multiple, :number def self.find_files(dir, progname, delete = false) files = Dir[File.join(dir, "#{progname}_num*.pid")] files = Dir[File.join(dir, "#{progname}.pid")] if files.size == 0 files.delete_if { |f| not (File.file?(f) and File.readable?(f)) } if delete files.delete_if do |f| pid = File.open(f) { |h| h.read }.to_i rsl = !Pid.running?(pid) if rsl begin; File.unlink(f); rescue ::Exception; end yield(pid, f) if block_given? end rsl end end files end def self.existing(path) new_instance = PidFile.allocate new_instance.instance_variable_set(:@path, path) def new_instance.filename @path end new_instance end def initialize(dir, progname, multiple = false) @dir = File.expand_path(dir) @progname = progname @multiple = multiple @number = nil @number = 0 if multiple if multiple while File.exist?(filename) && @number < 1024 @number += 1 end if @number >= 1024 fail RuntimeException('cannot run more than 1024 instances of the application') end end end def filename File.join(@dir, "#{@progname}#{@number ? '_num' + @number.to_s : '' }.pid") end def exist? File.exist? filename end def pid=(p) File.open(filename, 'w') do |f| f.chmod(0644) f.puts p # Process.pid end end def cleanup File.delete(filename) if pid == Process.pid end def zap File.delete(filename) if exist? end def pid begin File.open(filename) do |f| p = f.gets.to_i return nil if p == 0 # Otherwise an invalid pid file becomes pid 0 return p end rescue ::Exception return nil end end end end