-
-
Save sbusso/1978385 to your computer and use it in GitHub Desktop.
Simple ruby daemon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# == Simple Daemon | |
# | |
# A simple ruby daemon that you copy and change as needed. | |
# | |
# === How does it work? | |
# | |
# All this program does is fork the current process (creates a copy of | |
# itself) then exits, the fork (child process) then goes on to run your | |
# daemon code. In this example we are just running a while loop with a | |
# 1 second sleep. | |
# | |
# Most of the code is dedicated to managing a pid file. We want a pid | |
# file so we can use a monitoring tool to make sure our daemon keeps | |
# running. | |
# | |
# === Why? | |
# | |
# Writing a daemon sounds hard but as you can see is not that | |
# complicated, so lets strip away the magic and just write some ruby. | |
# | |
# === Usage | |
# | |
# You can run this daemon by running: | |
# | |
# $ ./simple_ruby_daemon.rb | |
# | |
# or with an optional pid file location as its first argument: | |
# | |
# $ ./simple_ruby_daemon.rb tmp/simple_ruby_daemon.pid | |
# | |
# check that it is running by running the following: | |
# | |
# $ ps aux | grep simple_ruby_daemon | |
# | |
# Author:: Rufus Post (mailto:rufuspost@gmail.com) | |
class SimpleDaemon | |
# Checks to see if the current process is the child process and if not | |
# will update the pid file with the child pid. | |
def self.start pid, pidfile, outfile, errfile | |
unless pid.nil? | |
raise "Fork failed" if pid == -1 | |
write pid, pidfile if kill pid, pidfile | |
exit | |
else | |
redirect outfile, errfile | |
end | |
end | |
# Attempts to write the pid of the forked process to the pid file. | |
def self.write pid, pidfile | |
File.open pidfile, "w" do |f| | |
f.write pid | |
end | |
rescue ::Exception => e | |
$stderr.puts "While writing the PID to file, unexpected #{e.class}: #{e}" | |
Process.kill "HUP", pid | |
end | |
# Try and read the existing pid from the pid file and signal the | |
# process. Returns true for a non blocking status. | |
def self.kill(pid, pidfile) | |
opid = open(pidfile).read.strip.to_i | |
Process.kill "HUP", opid | |
true | |
rescue Errno::ENOENT | |
$stdout.puts "#{pidfile} did not exist: Errno::ENOENT" | |
true | |
rescue Errno::ESRCH | |
$stdout.puts "The process #{opid} did not exist: Errno::ESRCH" | |
true | |
rescue Errno::EPERM | |
$stderr.puts "Lack of privileges to manage the process #{opid}: Errno::EPERM" | |
false | |
rescue ::Exception => e | |
$stderr.puts "While signaling the PID, unexpected #{e.class}: #{e}" | |
false | |
end | |
# Send stdout and stderr to log files for the child process | |
def self.redirect outfile, errfile | |
$stdin.reopen '/dev/null' | |
out = File.new outfile, "a" | |
err = File.new errfile, "a" | |
$stdout.reopen out | |
$stderr.reopen err | |
$stdout.sync = $stderr.sync = true | |
end | |
end | |
# Process name of your daemon | |
$0 = "simple ruby daemon" | |
# Spawn a deamon | |
SimpleDaemon.start fork, (ARGV[0] || '/tmp/deamon.pid'), (ARGV[1] || '/tmp/daemon.stdout.log'), (ARGV[2] || '/tmp/daemon.stderr.log') | |
# Set up signals for our daemon, for now they just exit the process. | |
Signal.trap("HUP") { $stdout.puts "SIGHUP and exit"; exit } | |
Signal.trap("INT") { $stdout.puts "SIGINT and exit"; exit } | |
Signal.trap("QUIT") { $stdout.puts "SIGQUIT and exit"; exit } | |
# Remove this loop and replace with your own daemon logic. | |
loop do | |
sleep 1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment