5

I have a script below using Thor to run like a rake task managing ARGV.

#!/usr/bin/env ruby
require "thor"

class Run < Thor

  desc "start", "start script"
  def start
      p1 = fork{ loop... }
      p2 = fork{ loop... }

      # 3 processes running

      Process.detach(p1)
      Process.waitpid(p1)

  end

  desc "stop", "stop script"      
  def stop
    # kill all 3 pids
  end

end

Run.start

When start ruby script.rb start, it generates two subprocesses (total three). My question is how to kill all processes when I execute ruby script.rb stop. I have seen around web that, on start, I should store the pid parent process into a file and, when stop, I read it and kill. The problem is that killing the parent doesn't kill the children. So I could save all three pids in the file and kill one by one later.

I'm asking myself what is the right way to do this, and whether the way I'm working with processes inside the start is correct.

Luccas
  • 4,078
  • 6
  • 42
  • 72
  • 2
    Storing the PID on the file system seems to be a fairly common practice of daemonized services, in your case it does sound like storing all the PIDs on the file system makes sense, it's the surest way to kill the correct processes. – Arthur Maltson Apr 23 '13 at 14:43
  • A possible alternative would be to attach a finalizer when the object gets GC'd that would properly clean up after itself. http://stackoverflow.com/questions/5956067/ruby-destructors You could also use Daemons gem to manage the processes. http://daemons.rubyforge.org/ – Bjoern Rennhak May 12 '13 at 01:14

1 Answers1

0

If you know your parent pid you can find and kill all the children like this:

# Find child pids, works on Linux / OSX
def child_pids(pid)
  pipe = IO.popen("ps -ef | grep #{pid}")
  pipe.readlines.map do |line|
    parts = line.strip.split(/\s+/)
    parts[1].to_i if parts[2] == pid.to_s and parts[1] != pipe.pid.to_s
  end.compact
end

# kill -9 every child
child_pids(parent_pid).each { |pid| Process.kill('TERM', pid) }
Spajus
  • 7,356
  • 2
  • 25
  • 26