Class: PidFile

Inherits:
Object
  • Object
show all
Defined in:
lib/pidfile.rb

Defined Under Namespace

Classes: DuplicateProcessError

Constant Summary collapse

VERSION =
'0.3.0'
DEFAULT_OPTIONS =
{
  :pidfile => File.basename($0, File.extname($0)) + ".pid",
  :piddir => '/tmp',
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ PidFile

Returns a new instance of PidFile.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/pidfile.rb', line 13

def initialize(*args)
  opts = {}

  #----- set options -----#
  case
  when args.length == 0 then
  when args.length == 1 && args[0].class == Hash then
    arg = args.shift

    if arg.class == Hash
      opts = arg
    end
  else
    raise ArgumentError, "new() expects hash or hashref as argument"
  end

  opts = DEFAULT_OPTIONS.merge opts

  @piddir     = opts[:piddir]
  @pidfile    = opts[:pidfile]
  @pidpath    = File.join(@piddir, @pidfile)
  @fh         = nil

  #----- Does the pidfile or pid exist? -----#
  if self.pidfile_exists?
    if self.class.running?(@pidpath)
      raise DuplicateProcessError, "Process (#{$0} - #{self.class.pid(@pidpath)}) is already running."
      
      exit! # exit without removing the existing pidfile
    end

    self.release
  end

  #----- create the pidfile -----#
  create_pidfile

  at_exit { release }
end

Instance Attribute Details

#piddirObject (readonly)

Returns the value of attribute piddir.



2
3
4
# File 'lib/pidfile.rb', line 2

def piddir
  @piddir
end

#pidfileObject (readonly)

Returns the value of attribute pidfile.



2
3
4
# File 'lib/pidfile.rb', line 2

def pidfile
  @pidfile
end

#pidpathObject (readonly)

Returns the value of attribute pidpath.



2
3
4
# File 'lib/pidfile.rb', line 2

def pidpath
  @pidpath
end

Class Method Details

.pid(path = nil) ⇒ Object

Returns the PID, if any, of the instantiating process



99
100
101
102
103
# File 'lib/pidfile.rb', line 99

def self.pid(path=nil)
  if pidfile_exists?(path)
    open(path, 'r').read.to_i
  end
end

.pidfile_exists?(path = nil) ⇒ Boolean

class method for determining the existence of pidfile

Returns:

  • (Boolean)


106
107
108
109
110
# File 'lib/pidfile.rb', line 106

def self.pidfile_exists?(path=nil)
  path ||= File.join(DEFAULT_OPTIONS[:piddir], DEFAULT_OPTIONS[:pidfile])

  File.exists?(path)
end

.running?(path = nil) ⇒ Boolean

boolean stating whether the calling program is already running

Returns:

  • (Boolean)


113
114
115
116
117
118
119
120
121
122
# File 'lib/pidfile.rb', line 113

def self.running?(path=nil)
  calling_pid = nil
  path ||= File.join(DEFAULT_OPTIONS[:piddir], DEFAULT_OPTIONS[:pidfile])

  if pidfile_exists?(path)
    calling_pid = pid(path)
  end

  process_exists?(calling_pid)
end

Instance Method Details

#alive?Boolean

Boolean stating whether this process is alive and running

Returns:

  • (Boolean)


69
70
71
72
73
# File 'lib/pidfile.rb', line 69

def alive?
  return false unless self.pid && (self.pid == Process.pid)

  self.class.process_exists?(self.pid)
end

#locktimeObject

returns the modification time of the pidfile



90
91
92
# File 'lib/pidfile.rb', line 90

def locktime
  File.mtime(self.pidpath)
end

#pidObject

Returns the PID, if any, of the instantiating process



58
59
60
61
62
63
64
65
66
# File 'lib/pidfile.rb', line 58

def pid
  return @pid unless @pid.nil?

  if self.pidfile_exists?
    @pid = open(self.pidpath, 'r').read.to_i
  else
    @pid = nil
  end
end

#pidfile_exists?Boolean

does the pidfile exist?

Returns:

  • (Boolean)


76
77
78
# File 'lib/pidfile.rb', line 76

def pidfile_exists?
  self.class.pidfile_exists?(pidpath)
end

#releaseObject

unlock and remove the pidfile. Sets pid to nil



81
82
83
84
85
86
87
# File 'lib/pidfile.rb', line 81

def release
  unless @fh.nil?
    @fh.flock(File::LOCK_UN)
    remove_pidfile
  end
  @pid = nil
end