DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Ruby Daemon Module
The following code lets you implement a daemon very easily, and also lets you write cleanup code.
Update: I made some small changes to make it look slightly better.
require 'fileutils'
module Daemon
WorkingDirectory = File.expand_path(File.dirname(__FILE__))
class Base
def self.pid_fn
File.join(WorkingDirectory, "#{name}.pid")
end
def self.daemonize
Controller.daemonize(self)
end
end
module PidFile
def self.store(daemon, pid)
File.open(daemon.pid_fn, 'w') {|f| f << pid}
end
def self.recall(daemon)
IO.read(daemon.pid_fn).to_i rescue nil
end
end
module Controller
def self.daemonize(daemon)
case !ARGV.empty? && ARGV[0]
when 'start'
start(daemon)
when 'stop'
stop(daemon)
when 'restart'
stop(daemon)
start(daemon)
else
puts "Invalid command. Please specify start, stop or restart."
exit
end
end
def self.start(daemon)
fork do
Process.setsid
exit if fork
PidFile.store(daemon, Process.pid)
Dir.chdir WorkingDirectory
File.umask 0000
STDIN.reopen "/dev/null"
STDOUT.reopen "/dev/null", "a"
STDERR.reopen STDOUT
trap("TERM") {daemon.stop; exit}
daemon.start
end
end
def self.stop(daemon)
if !File.file?(daemon.pid_fn)
puts "Pid file not found. Is the daemon started?"
exit
end
pid = PidFile.recall(daemon)
FileUtils.rm(daemon.pid_fn)
pid && Process.kill("TERM", pid)
end
end
end
To use it, you can do something like the following:
class Counter < Daemon::Base
def self.start
@a = 0
loop do
@a += 1
end
end
def self.stop
File.open('result', 'w') {|f| f.puts "a = #{@a}"}
end
end
Counter.daemonize






Comments
Snippets Manager replied on Sun, 2006/08/06 - 1:46am
Snippets Manager replied on Mon, 2012/05/07 - 2:25pm