Servolux: monitoring outside change?

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 => Class: Process::Status (Ruby 1.9.3)
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

···

On Jan 10, 2012, at 1:05 PM, 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"
=> #<Servolux::child:0xb7024290
@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
=> #<IO:0xb701c6bc>
[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"
=> #<Servolux::child:0x84d68c4
@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
=> #<IO:fd 3>
[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] <defunct>

Exiting the irb/pry session lets the sleep process finally die a peaceful
death.

Would this count as a bug in Servolux?

You need to reap the child PID otherwise you'll end up with a zombie process. You do this by calling Process.wait on the child PID. The Servolux::Child class has this built in via the wait method.

require 'servolux'
child = Servolux::Child.new :command => 'sleep 600'
child.wait
# now kill -9 the child process in a separate window
child.signaled? #=> true
child.termsig #=> 9

Hope that explains it a little more. Ruby has no way to know if the child process has been killed or not until you attempt to access the child again. Calling the wait method will cause Ruby to refresh it's knowledge of the child.

Blessings,
TwP

···

On Jan 10, 2012, at 9:07 PM, Aldric Giacomoni wrote:

--Aldric

On Tue, Jan 10, 2012 at 21:44, Tim Pease <tim.pease@gmail.com> 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 =>
Class: Process::Status (Ruby 1.9.3)
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

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 Jan 11, 2012, at 9:51 AM, Aldric Giacomoni wrote:

On Wed, Jan 11, 2012 at 11:10, Aldric Giacomoni <trevoke@gmail.com> 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 <trevoke@gmail.com> 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"
=> #<Servolux::child:0xb7024290
@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
=> #<IO:0xb701c6bc>
[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"
=> #<Servolux::child:0x84d68c4
@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
=> #<IO:fd 3>
[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] <defunct>

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 <tim.pease@gmail.com> 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 =>
Class: Process::Status (Ruby 1.9.3)
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