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'
Signal.trap('INT') { Pidify.stop; exit }
module Doer
def self.start
puts "starting"
Pidify.start_as_daemon
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
-
.daemonize ⇒ Object
Daemonizes this process.
-
.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.
-
.start_as_daemon ⇒ Object
Like Pidify.start, but first calls Pidify.daemonize.
-
.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
.daemonize ⇒ Object
Daemonizes this process. Does not automatically use a PID file. If you want to use a PID file, you must call Pidify.start after the call to daemonize or use Pidify.start_as_daemon.
213 214 215 216 217 218 219 220 221 |
# File 'lib/pidify.rb', line 213 def daemonize fork and exit Process.setsid Dir.chdir '/' File.umask 0000 STDIN.reopen "/dev/null" STDOUT.reopen "/dev/null", "a" STDERR.reopen STDOUT end |
.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.
145 146 147 148 149 150 151 152 153 154 |
# File 'lib/pidify.rb', line 145 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.
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/pidify.rb', line 114 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).
77 78 79 |
# File 'lib/pidify.rb', line 77 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.
85 86 87 88 |
# File 'lib/pidify.rb', line 85 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.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/pidify.rb', line 184 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.
96 97 98 |
# File 'lib/pidify.rb', line 96 def pid_exists? return FileTest.exists?(pid_file) end |
.pid_file ⇒ Object
Returns the PID filename as a Pathname.
91 92 93 |
# File 'lib/pidify.rb', line 91 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.
101 102 103 104 105 106 107 108 109 |
# File 'lib/pidify.rb', line 101 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.
129 130 131 132 133 134 135 136 137 |
# File 'lib/pidify.rb', line 129 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.
159 160 161 162 |
# File 'lib/pidify.rb', line 159 def start raise "Failed to start: already running (PID file exists)." if pid_exists? return true if save_pid end |
.start_as_daemon ⇒ Object
Like Pidify.start, but first calls Pidify.daemonize. Will fail and raise an exception if Pidify.running? returns true.
204 205 206 207 208 |
# File 'lib/pidify.rb', line 204 def start_as_daemon raise "Failed to start: already running." if running? daemonize start 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.
167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/pidify.rb', line 167 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 |