From: Tim Pease Date: 2012-01-12T03:00:01+09:00 Subject: Re: Servolux: monitoring outside change? On Jan 11, 2012, at 9:51 AM, Aldric Giacomoni wrote: > Daemons seemed to fit the bill: long-running process in the background. > > Sadly, I ran into an issue in my unit tests where the Daemon would actually > run so fast that Ruby would miss the start of it. Since that's not going to > happen in my configuration in real life, I just made the script run a > little longer. > > Now, here is my current situation. Upon completion of a test where the > Daemon.new.startup is called, the entire test suite stops running. The > script runs properly. My unit test checks that upon completion, the script > has done what it needs to do, so imagine this: > > def test_launches_outside_process > at_exit { assert_equal 100, Dir['/tmp/*'] } > Manager.new.launch {some => args, here => to, help => out} > end > > Now, the launch command: > class Manager > def launch args > daemon = Servolux::Daemon.new :startup_command => "/path/to/cmd with > args", :name => "name", :pid_file => "/tmp/pid", :logger => > Logger.new('/tmp/log.log') > daemon.startup > at_exit { daemon.shutdown } > daemon > end > end > > From what I understand of the implementation, the daemon process, calling > Kernel.exec, actually REPLACES the Ruby process. I realize it's supposed to > fork up in the startup method, but ... How, then, can I use one single Ruby > process to launch many daemons? > > I wrote a small script to identify my problem (maybe I'm thinking about it > incorrectly): > #!/usr/bin/env ruby > > require 'rubygems' > require 'servolux' > require 'logger' > > x = Servolux::Daemon.new :name => 'hello', :logger => > Logger.new('/tmp/aldric.log'), :startup_command => 'sleep 600', :pid_file > => '/tmp/aldric.pid' > x.startup > p "hello" while true > > This script does NOT print 'hello'. It returns to the command line and > sleep is now running in the background. > > So.. If the Daemon object is really only meant to configure and start a > daemon, then I -do- want a Child object, don't I. > Thanks for the answer. The problem I have with calling 'wait' on the Child > object is that I block my top-level process until I get more information > from that child. I'm going to be in a situation where I have 20+ children > all running. How can I monitor them all? Can I call Process.waitall and get > the same result? > When you start the daemon, pass +false+ to the startup method. This will prevent exiting from the parent process after the daemon process is determined to be running. http://rubydoc.info/gems/servolux/0.9.6/Servolux/Daemon:startup Blessings, TwP > On Wed, Jan 11, 2012 at 11:10, Aldric Giacomoni wrote: > >> Oh, I see. What I want to use here is a daemon, not a child. >> >> >> On Tue, Jan 10, 2012 at 23:07, Aldric Giacomoni wrote: >> >>> Thanks for the answer. I decided to try that behavior, and here is the >>> result (sadly, negative). I must be doing something wrong... But what? >>> Ruby 1.8.7-p357: >>> $ pry >>> [1] pry(main)> require 'servolux' >>> => true >>> [2] pry(main)> x = Servolux::Child.new :command => "sleep 600" >>> => #>> @command="sleep 600", @io=nil, @pid=nil, >>> @signals=["TERM", "QUIT", "KILL"], @status=nil, >>> @suspend=4, @thread=nil, @timed_out=nil, @timeout=nil> >>> [3] pry(main)> x.start >>> => # >>> [4] pry(main)> x.pid >>> => 17152 >>> >>> (at this point, I do a $ kill -9 17152 in another terminal) >>> >>> [5] pry(main)> x.signaled? >>> => nil >>> [6] pry(main)> x.termsig >>> => nil >>> >>> Same test with Ruby 1.9.2-p290: >>> >>> $ pry >>> [1] pry(main)> RUBY_VERSION >>> => "1.9.2" >>> [2] pry(main)> require 'servolux' >>> => true >>> [3] pry(main)> x = Servolux::Child.new :command => "sleep 600" >>> => #>> @command="sleep 600", >>> @io=nil, >>> @pid=nil, >>> @signals=["TERM", "QUIT", "KILL"], >>> @status=nil, >>> @suspend=4, >>> @thread=nil, >>> @timed_out=nil, >>> @timeout=nil> >>> [4] pry(main)> x.start >>> => # >>> [5] pry(main)> x.pid >>> => 17614 >>> >>> (again, kill -9 17614 in another terminal) >>> >>> [9] pry(main)> x.signaled? >>> => nil >>> [10] pry(main)> x.termsig >>> => nil >>> >>> In both situations, doing a 'ps eax | grep sleep' revealed the following: >>> 17614 pts/5 ZN+ 0:00 [sleep] >>> >>> Exiting the irb/pry session lets the sleep process finally die a peaceful >>> death. >>> >>> Would this count as a bug in Servolux? >>> >>> --Aldric >>> >>> On Tue, Jan 10, 2012 at 21:44, Tim Pease wrote: >>> >>>> >>>> On Jan 10, 2012, at 1:05 PM, Aldric Giacomoni wrote: >>>> >>>>> Hi Tim, >>>>> >>>>> I started using Servolux on a small internal project and so far I'm >>>> really >>>>> pleased with it. What I'm doing is very simple: I have to manage a few >>>>> scripts and start them with the right command-line arguments (does the >>>>> acronym CLA mean anything to anyone? I've never seen it used but it >>>> would >>>>> make my life so much easier). I use Servolux::Child objects for that. >>>>> >>>> >>>> I'm glad you are finding Servolux useful! >>>> >>>>> Is there a way, internally, to know whether one of the processes >>>> handled by >>>>> the Child object has been kill-9'd by, say, an outside human hand? I >>>> don't >>>>> really know enough about the popen stuff and process communication to >>>>> figure that out. >>>>> >>>> >>>> The Servolux::Child class provides several methods to determine the >>>> status of the child process. >>>> >>>> * alive? -- This method returns +true+ if the child process is still >>>> alive. So if someone kills the process (kill -9) then this method will >>>> return +false+. If this method returns +nil+, the the child process was >>>> never started. >>>> >>>> There are several methods that map directly to the ruby Process::Status >>>> class and can be used to find out exactly how and why the child process >>>> exited. All of these methods can be called on your Servolux::Child instance: >>>> >>>> * coredump? >>>> * exited? >>>> * signaled? >>>> * stopped? >>>> * success? >>>> * exitstatus >>>> * stopsig >>>> * termsig >>>> >>>> You can read the documentation for these methods here => >>>> http://ruby-doc.org/core-1.9.3/Process/Status.html >>>> In your case the methods to look at are "signaled?" and "termsig". If >>>> "termsig" returns 9, then someone used kill -9 to stop the process. >>>> >>>> Hope all this helps! >>>> >>>> Blessings, >>>> TwP >>> >>> >>> >>