Running a Daemon Process on Unix

Problem

You want to run a process in the background with minimal interference from users and the operating system.

Solution

In Ruby 1.9, you can simply call Process.daemon to turn the current process into a daemon. Otherwise, the most reliable way is to use the Daemonize module. Its not available as a gem, but its worth downloading and installing, because it makes it easy and reliable to write a daemon:

	#!/usr/bin/ruby -w
	# 
daemonize_daemon.rb
	require 	empfile
	require daemonize
	include Daemonize # Import Daemonize::daemonize into this namespace

	puts About to daemonize.
	daemonize # Now you
e a daemon process!
	log = Tempfile.new(daemon.log)
	loop do
	 log.puts "Im a daemon, doin daemon things."
	 log.flush
	 sleep 5
	end

If you run this code at the command line, youll get back a new prompt almost immediately. But there will still be a Ruby process running in the background, writing to a temporary file every five seconds:

	$ ./daemonize_daemon.rb
	About to daemonize.
	$ ps x | grep daemon
	4472 ? S 0:00 ruby 
daemonize_daemon.rb
	4474 pts/2 S+ 0:00 grep daemon

	$ cat /tmp/daemon.log4472.0
	Im a daemon, doin daemon things.
	Im a daemon, doin daemon things.
	Im a daemon, doin daemon things.

Since it runs an infinite loop, this daemon process will run until you kill it:

	$ kill 4472

	$ ps x | grep daemon
	 4569 pts/2 S+ 0:00 grep daemon

A different daemon might run until some condition is met, or until it receives a Unix signal, or a "stop" message through some interface.

Discussion

A daemon process is one that runs in the background, without any direct user interface at all. Servers are usually daemon processes, but you might also write a daemon to do monitoring or task scheduling.

Rather than replacing your process with a daemon process, you may want to spawn a daemon while continuing with your original work. The best strategy for this is to spawn a subprocess with Kernel#fork.

Rubys fork implementation takes a code block to be run by the subprocess. The code defined after the block is run in the original process. So pass your daemonizing code into fork, and continue with your work in the main body of the code:

	#!/usr/bin/ruby -w
	# daemon_spawn.rb
	require 	empfile
	require  
daemonize
	include Daemonize

	puts "About to daemonize."
	fork do
	 daemonize
	 log = Tempfile.new(daemon.log)
	 loop do
	 log.puts "Im a daemon, doin daemon things."
	 log.flush
	 sleep 5
	 end
	end

	puts The subprocess has become a daemon.
	puts "But Im going to stick around for a while."
	sleep 10
	puts "Okay, now Im done."

The Daemonize code fits in a single file, and its licensed under the same terms as Ruby. If you don want to require your users to download and install it, you can just include it with your program. Because the code is short, you can even copy-and-paste the code into a file in your own program.

However, theres also some (less fancy) daemonizing code in the Ruby 1.8 standard library. Its the WEBrick::Daemon class.

	#!/usr/bin/ruby
	# webrick_daemon.rb
	require 	empfile
	require webrick

	puts About to 
daemonize.
	WEBrick::Daemon.start do
	 log = Tempfile.new(daemon.log)
	 loop do
	 log.puts "Im a daemon, doin daemon things."
	 log.flush
	 sleep 5
	 end
	end

Its worth examining the simpler daemonizing code in WEBrick::Daemon so that you can see whats going on. Heres the method in question:

	def Daemon.start
	 exit!(0) if fork
	 Process::setsid
	 exit!(0) if fork
	 Dir::chdir("/")
	 File::umask(0)
	 STDIN.reopen("/dev/null")
	 STDOUT.reopen("/dev/null", "w")
	 STDERR.reopen("/dev/null", "w")
	 yield if block_given?
	end

A daemonizer works by forking a new process, letting the original one die, and closing off some of the resources that were available to the original.

Process::setsid disconnects the daemon from the terminal that spawned it. This is why, when your process becomes a daemon process, you get your command line back immediately. We close the original standard input, output, and error and replace them with null streams. We set the working directory and file umask to sensible defaults, regardless of what the daemon inherited from the parent. Then we run the daemon code.

Daemonize::daemonize also sets up signal handlers, calls srand so that the daemon process has a new random number seed, and (optionally) closes any open file handles left around by the original process. It can also retry the fork if it fails because the operating system is running too many processes to create another one.

The fork method, and methods like daemonize that depend on it, are only available on Unix-like systems. On Windows, the win32-process extension provides Windows implementations of methods like fork. The win32-process implementation of fork isn perfect, but its there if you need it. For cross-platform code, we recommend you spawn a thread and run your daemon code in the thread.

See Also

  • The Daemonize package (http://grub.ath.cx/daemonize/ )
  • If you want to run an Internet server, you might want to use gserver from Rubys standard library; see Recipe 14.14, "Writing an Internet Server"
  • A service is the Windows equivalent of a daemon process; see Recipe 20.2, " Creating a Windows Service"
  • Recipe 20.3, "Doing Two Things at Once with Threads"
  • Both win32-process and win32-service were written by Daniel J. Berger; you can download them from his win32utils project at http://rubyforge.org/projects/win32utils/
  • Get win32-process from http://rubyforge.org/projects/win32utils/


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net