Created
November 17, 2011 06:09
-
-
Save mynameisrufus/1372491 to your computer and use it in GitHub Desktop.
Revisions
-
mynameisrufus revised this gist
Mar 15, 2012 . 1 changed file with 125 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,125 @@ #!/usr/bin/env ruby # == Double-forking Unix daemon # # Author:: Rufus Post (mailto:rufuspost@gmail.com) # # === How does it work? # # According to Stevens's Advanced Programming in the UNIX Environment # chapter 13, this is the procedure to make a well-behaved Unix daemon: # # Fork and have the parent exit. This makes the shell or boot script # think the command is done. Also, the child process is guaranteed not # to be a process group leader (a prerequisite for setsid next) # Call setsid to create a new session. This does three things: # * The process becomes a session leader of a new session # * The process becomes the process group leader of a new process group # * The process has no controlling terminal # # Optionally fork again and have the parent exit. This guarantes that # the daemon is not a session leader nor can it acquire a controlling # terminal (under SVR4) # # grandparent - the current process # \_ parent - exits immediately # \_ simple daemon - writes out its pid to file # # Change the current working directory to / to avoid interfering with # mounting and unmounting. By default don't bother to chdir("/") here # because we might to run inside APP_ROOT. # # Set file mode creation mask to 000 to allow creation of files with any # required permission later. By default umask is whatever was set by the # parent process at startup and can be set in config.ru and config_file, # so making it 0000 and potentially exposing sensitive log data can be # bad policy. # # Close unneeded file descriptors inherited from the parent (there is no # controlling terminal anyway): stdout, stderr, and stdin. # # Nowadays there is a file to track the PID which is used heavily by # Linux distribution boot scripts. Be sure to write out the PID of the # grandchild, either the return value of the second fork (step 3) or the # value of getpid() after step 3. # class SimpleDaemon # In the directory where you want your daemon add a git submodule to # your project and create a daemon launcher script: # # #!/usr/bin/env ruby # # require 'simple_daemon' # # $0 = "my daemon" # # SimpleDaemon.daemonize! ARGV[0], ARGV[1], ARGV[2] # # loop do # sleep 5 # puts "tick" # sleep 5 # puts "tock" # end # # make your script executable and run: # # $ chmod +x launcher # $ launcher tmp/daemon.pid log/daemon.stdout.log log/daemon.stderr.log # # check that it is running by with the following: # # $ ps aux | grep "my daemon" # # def self.daemonize! pidfile, out = '/dev/null', err = '/dev/null', safe = true raise 'First fork failed' if (pid = fork) == -1 exit unless pid.nil? Process.setsid raise 'Second fork failed' if (pid = fork) == -1 exit unless pid.nil? kill pidfile write Process.pid, pidfile unless safe Dir.chdir '/' File.umask 0000 end redirect out, err end # Attempts to write the pid of the forked process to the pid file. # Kills process if write unsuccesfull. def self.write pid, pidfile File.open pidfile, "w" do |f| f.write pid f.close end $stdout.puts "Daemon running with pid: #{pid}" rescue ::Exception => e raise "While writing the PID to file, unexpected #{e.class}: #{e}" end # Try and read the existing pid from the pid file and signal HUP to # process. def self.kill pidfile opid = open(pidfile).read.strip.to_i Process.kill "HUP", opid rescue TypeError $stdout.puts "#{pidfile} was empty: TypeError" rescue Errno::ENOENT $stdout.puts "#{pidfile} did not exist: Errno::ENOENT" rescue Errno::ESRCH $stdout.puts "The process #{opid} did not exist: Errno::ESRCH" rescue Errno::EPERM raise "Lack of privileges to manage the process #{opid}: Errno::EPERM" rescue ::Exception => e raise "While signaling the PID, unexpected #{e.class}: #{e}" end # Redirect file descriptors inherited from the parent. def self.redirect out, err $stdin.reopen '/dev/null' $stdout.reopen File.new(out, "a") $stderr.reopen File.new(err, "a") $stdout.sync = $stderr.sync = true end end -
mynameisrufus revised this gist
Mar 15, 2012 . 2 changed files with 2 additions and 110 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ tmp log doc daemon *.swp This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,110 +0,0 @@ -
mynameisrufus revised this gist
Mar 14, 2012 . 2 changed files with 16 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,3 @@ tmp log *.swp This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -8,7 +8,7 @@ # 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 # that outputs 'tick' and 'tock'. # # 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 @@ -25,22 +25,23 @@ # # $ ./simple_ruby_daemon.rb # # or with arguments: # # $ ./simple_ruby_daemon.rb tmp/daemon.pid log/daemon.stdout.log log/daemon.stderr.log # # 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? redirect outfile, errfile raise "Fork failed" if pid == -1 write pid, pidfile if kill pidfile exit else redirect outfile, errfile @@ -51,6 +52,7 @@ def self.start pid, pidfile, outfile, errfile def self.write pid, pidfile File.open pidfile, "w" do |f| f.write pid f.close end rescue ::Exception => e $stderr.puts "While writing the PID to file, unexpected #{e.class}: #{e}" @@ -59,7 +61,7 @@ def self.write pid, pidfile # Try and read the existing pid from the pid file and signal the # process. Returns true for a non blocking status. def self.kill pidfile opid = open(pidfile).read.strip.to_i Process.kill "HUP", opid true @@ -92,7 +94,7 @@ def self.redirect outfile, errfile $0 = "simple ruby daemon" # Spawn a deamon SimpleDaemon.start fork, (ARGV[0] || 'tmp/daemon.pid'), (ARGV[1] || 'log/daemon.stdout.log'), (ARGV[2] || 'log/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 } @@ -101,5 +103,8 @@ def self.redirect outfile, errfile # Remove this loop and replace with your own daemon logic. loop do sleep 5 puts "tick" sleep 5 puts "tock" end -
mynameisrufus revised this gist
Mar 5, 2012 . 1 changed file with 19 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -37,16 +37,18 @@ 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 @@ -74,18 +76,28 @@ def self.kill(pid, pidfile) $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 -
mynameisrufus revised this gist
Nov 17, 2011 . 1 changed file with 8 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -11,13 +11,13 @@ # 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 # @@ -29,7 +29,7 @@ # # $ ./simple_ruby_daemon.rb tmp/simple_ruby_daemon.pid # # check that it is running by running the following: # # $ ps aux | grep simple_ruby_daemon # @@ -58,16 +58,17 @@ def self.write(pid, pidfile) # 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}" @@ -89,4 +90,4 @@ def self.kill(pid, pidfile) # Remove this loop and replace with your own daemon logic. loop do sleep 1 end -
mynameisrufus created this gist
Nov 17, 2011 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,92 @@ #!/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 your 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 # # You can 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) unless pid.nil? raise "Fork failed" if pid == -1 write(pid, pidfile) if kill(pid, pidfile) exit 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) Process.kill "HUP", open(pidfile).read.strip.to_i true rescue Errno::ENOENT $stdout.puts "#{pidfile} did not exist: Errno::ENOENT" true rescue Errno::ESRCH $stdout.puts "Process for the existing PID was not running: Errno::ESRCH" true rescue Errno::EPERM $stderr.puts "Lack of privileges to manage #{pidfile}: Errno::EPERM" false rescue ::Exception => e $stderr.puts "While signaling the PID, unexpected #{e.class}: #{e}" false end end # Process name of your daemon $0 = "simple ruby daemon" # Spawn a deamon SimpleDaemon.start fork, (ARGV.first || '/tmp/simple_ruby_deamon.pid') # Set up signals for our daemon, for now they just exit the process. Signal.trap("HUP") { puts "SIGHUP and exit"; exit } Signal.trap("INT") { puts "SIGINT and exit"; exit } Signal.trap("QUIT") { puts "SIGQUIT and exit"; exit } # Remove this loop and replace with your own daemon logic. loop do sleep 1 end