Module: Pidify
- Defined in:
- lib/pidify.rb
Overview
Use the module methods in Pidify to save/delete the PID of a running script, or kill a running script using a saved PID.
Example:
require 'pidify'
Pidify.running? # => false
Pidify.start
Pidify.running? # => true
puts "I am running with PID #{Pidify.pid}!"
Pidify.stop
Pidify.running? # => false
A more useful example:
require 'pidify'
require 'daemons'
Signal.trap('INT') { Pidify.stop; exit }
module Doer
def self.start
puts "starting"
raise "Failed to start: already running." if Pidify.running?
Daemons.daemonize
Pidify.start
loop do
puts "hello world"
sleep 1
end
end
end
if ARGV.include? 'stop'
Pidify.stop
puts "Daemon stopped."
else
puts "Daemon starting."
Doer.start
end
Class Method Summary collapse
-
.delete_pid ⇒ Object
Deletes the PID file.
-
.pid ⇒ Object
Returns the PID stored in the pid_file (not necessarily the PID of this script).
-
.pid_directory ⇒ Object
Returns the Pathname of the PID storage directory (defaults to /var/run).
-
.pid_directory=(dir) ⇒ Object
Sets the PID storage directory (defaults to /var/run).
-
.pid_end(signals = %w(SIGTERM SIGQUIT SIGKILL), secs_between_signal = 4) ⇒ Object
Sends each kill signal to the saved PID, pausing for secs_between_signal after each to check if it the process remains running.
-
.pid_exists? ⇒ Boolean
Returns true if the pid_file exists for this script.
-
.pid_file ⇒ Object
Returns the PID filename as a Pathname.
-
.running? ⇒ Boolean
Returns true if the process using pid is running.
-
.save_pid ⇒ Object
Saves the PID of this script into the pid_file.
-
.start ⇒ Object
Saves the PID of this script into the pid_file by calling save_pid.
-
.stop(signals = %w(SIGTERM SIGQUIT SIGKILL), secs_between_signal = 4) ⇒ Object
Deletes the saved PID file and, if the PID belongs to a process different from this script, sends kill signals to the saved PID using pid_end.
Class Method Details
.delete_pid ⇒ Object
Deletes the PID file. Calling stop calls this automatically, but will also try to send a kill signal to the running process, if it is different from this one. BEWARE that this tries to delete whatever file is returned by pid_file and does no error checking on it! Returns true if the delete was successful, false if there was an error, and nil if the pid file doesn’t exist.
140 141 142 143 144 145 146 147 148 149 |
# File 'lib/pidify.rb', line 140 def delete_pid return nil unless pid_exists? begin # FIXME: lock first? File.delete(pid_file) true rescue false end end |
.pid ⇒ Object
Returns the PID stored in the pid_file (not necessarily the PID of this script). Returns nil if no PID exists or if there is a problem with the read.
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/pidify.rb', line 109 def pid return nil unless pid_exists? dpid = nil begin File.open(pid_file, File::RDONLY) { |file| dpid = file.gets.chomp if file.flock(File::LOCK_SH|File::LOCK_NB); file.flock(File::LOCK_UN) } rescue return nil end return dpid.to_i if dpid && dpid.to_i > 0 nil end |
.pid_directory ⇒ Object
Returns the Pathname of the PID storage directory (defaults to /var/run).
72 73 74 |
# File 'lib/pidify.rb', line 72 def pid_directory @pid_directory end |
.pid_directory=(dir) ⇒ Object
Sets the PID storage directory (defaults to /var/run). Be VERY CAREFUL using this, as delete_pid will try to delete whatever file it thinks is the pid_file for this script in the pid_directory. It’s probably a good idea not to change this at all.
80 81 82 83 |
# File 'lib/pidify.rb', line 80 def pid_directory=(dir) @pid_directory = Pathname.new(dir) unless dir.kind_of? Pathname @pid_directory = dir if dir.kind_of? Pathname end |
.pid_end(signals = %w(SIGTERM SIGQUIT SIGKILL), secs_between_signal = 4) ⇒ Object
Sends each kill signal to the saved PID, pausing for secs_between_signal after each to check if it the process remains running. Stops when the process has ended or when all signals have been tried. Returns true if the process was killed or false otherwise.
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/pidify.rb', line 179 def pid_end(signals=%w(SIGTERM SIGQUIT SIGKILL), secs_between_signal=4) pid = self.pid signals = [ signals ].flatten.map{|sig| sig.to_s} existed = false signals.each do |sig| begin Process.kill(sig, pid) existed = true rescue Errno::ESRCH return (existed ? true : nil) end return true unless running? sleep secs_between_signal return true unless running? end not running? end |
.pid_exists? ⇒ Boolean
Returns true if the pid_file exists for this script.
91 92 93 |
# File 'lib/pidify.rb', line 91 def pid_exists? return FileTest.exists?(pid_file) end |
.pid_file ⇒ Object
Returns the PID filename as a Pathname.
86 87 88 |
# File 'lib/pidify.rb', line 86 def pid_file @pid_directory + (Pathname.new(@file_name).basename.to_s+'.pid') end |
.running? ⇒ Boolean
Returns true if the process using pid is running.
96 97 98 99 100 101 102 103 104 |
# File 'lib/pidify.rb', line 96 def running? return false unless pid_exists? begin Process::kill 0, pid true rescue Errno::ESRCH false end end |
.save_pid ⇒ Object
Saves the PID of this script into the pid_file. Automatically called by start. Returns nil if the pid file already exists. Returns true if successful, false if there was a write problem.
124 125 126 127 128 129 130 131 132 |
# File 'lib/pidify.rb', line 124 def save_pid return nil if pid_exists? begin File.open(pid_file, File::CREAT|File::EXCL|File::WRONLY) { |file| file.puts $$ if file.flock(File::LOCK_EX); file.flock(File::LOCK_UN) } true rescue false end end |
.start ⇒ Object
Saves the PID of this script into the pid_file by calling save_pid. Raises an exception if pid_exists? returns false. Returns true if successful.
154 155 156 157 |
# File 'lib/pidify.rb', line 154 def start raise "Failed to start: already running (PID file exists)." if pid_exists? return true if save_pid end |
.stop(signals = %w(SIGTERM SIGQUIT SIGKILL), secs_between_signal = 4) ⇒ Object
Deletes the saved PID file and, if the PID belongs to a process different from this script, sends kill signals to the saved PID using pid_end. Returns true if the process was killed or false otherwise.
162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/pidify.rb', line 162 def stop(signals=%w(SIGTERM SIGQUIT SIGKILL), secs_between_signal=4) return false unless pid_exists? unless running? delete_pid return true end pid = self.pid killed = true killed = pid_end(signals, secs_between_signal) if pid != $$ delete_pid if killed == true killed end |