Daemonizing ruby
21 November 2008
This edition of PoolParty internals is going to show you how to run a block of ruby. Considering that you know a little bit of ruby, I’ll be going a little faster in this post.
There are a few commands right now in PoolParty that allow you to daemonize the process with the -d flag. (Future post on extending the OptionParser). This will place the block of code in the binary into the daemonized mode.
From within PoolParty, this command looks like:
def daemonize(&block)
vputs "Daemonizing..."
pid = fork do
Signal.trap('HUP', 'IGNORE') # Don't die upon logout
File.open("/dev/null", "r+") do |devnull|
$stdout.reopen(devnull)
$stderr.reopen(devnull)
$stdin.reopen(devnull) unless @use_stdin
end
block.call if block
end
Process.detach(pid)
pid
end
I’ll walk through this snippet of ruby with you.
First off, vputs is a PoolParty internal to print verbosely, so we can ignore that for now. Basically, it calls put if verbose is set on the containing object. Until the post referenced above is written, just trust that it puts if verbose is set.
Second, we use Kernel.fork to create a subprocess from within ruby. Second, we tell the subprocess not to quit if it receives the linux signal ‘HUP.’ This way, we can safely ignore the process and assume it will continue to run even if we do log out or our OS sends it a HUP signal.
Then we’ll pipe the output to /dev/null so that we don’t see any output on the daemonzied process. It would be odd to daemonize a process and see output after we’ve forked it off.
Finally, we’ll use the block that we’ll send it when calling daemonize before detaching the process from this process. Detaching the process will set the process apart from this parent process and assume that it is it’s own parent process. This way, our process won’t receive any errors if the forked one does.
You can call daemonize with a block, like so
daemonize do
sum = (1..12000000).inject(0) do |sum,i|
sum + i
end
File.open("/tmp/sum", "w+") {|f| f << sum}
end
That completes this edition of inside PoolParty. Stay tuned for the next one!
Code has been attached daemonize.
Update
def daemonize(&block)
trap("CHLD") {Process.wait(-1, Process::WNOHANG)}
fork do
Signal.trap('HUP', 'IGNORE') # Don't die upon logout
File.open("/dev/null", "r+") do |devnull|
$stdout.reopen(devnull)
$stderr.reopen(devnull)
$stdin.reopen(devnull) unless @use_stdin
end
block.call if block
end
end
This sets the flag ruby to not block if no child is available and waits for any child process of the current execution block (see Process)
Also, one more note: my MacBook is officially dead and en route to Apple, so updates to PoolParty may be slow this week.
Comments
blog comments powered by Disqus