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