#!/usr/bin/env ruby require "json" require "yaml" class ProcessMonitor SIGNALS = %w[ INT TERM CLD ] def initialize(procfile) @procs = process_list(procfile) handle_signals @procs.each &:start @procs.each &:wait end private def process_list(procfile) config = YAML.load_file(procfile) config.map { |name, cmd| MonitoredProcess.new(name, cmd) } end def handle_signals SIGNALS.each do |signal| Signal.trap(signal) do @procs.each &:terminate end end end end class MonitoredProcess def initialize(name, cmd) @name, @cmd = name, cmd end def start @pid = Process.spawn(@cmd) end def wait Process.wait @pid rescue Errno::ECHILD nil end def terminate Process.kill "TERM", @pid rescue Errno::ESRCH nil end end ProcessMonitor.new("Procfile")