lib/foreman/engine.rb in foreman-0.2.0 vs lib/foreman/engine.rb in foreman-0.3.0

- old
+ new

@@ -1,24 +1,31 @@ require "foreman" require "foreman/process" +require "pty" require "tempfile" +require "term/ansicolor" class Foreman::Engine attr_reader :procfile attr_reader :directory + extend Term::ANSIColor + + COLORS = [ cyan, yellow, green, magenta, on_blue ] + def initialize(procfile) @procfile = read_procfile(procfile) @directory = File.expand_path(File.dirname(procfile)) end def processes @processes ||= begin procfile.split("\n").inject({}) do |hash, line| next if line.strip == "" process = Foreman::Process.new(*line.split(" ", 2)) + process.color = next_color hash.update(process.name => process) end end end @@ -30,11 +37,11 @@ end trap("TERM") { kill_and_exit("TERM") } trap("INT") { kill_and_exit("INT") } - run_loop + watch_for_termination end def screen tempfile = Tempfile.new("foreman") tempfile.puts "sessionname foreman" @@ -67,27 +74,33 @@ proctitle "ruby: foreman #{process.name}" Dir.chdir directory do FileUtils.mkdir_p "log" command = process.command - command << " >>log/#{process.name}.log 2>&1" if log_to_file - system command - exit $?.exitstatus || 255 + + PTY.spawn("#{process.command} 2>&1") do |stdin, stdout, pid| + until stdin.eof? + info stdin.gets, process + end + end end end def kill_and_exit(signal="TERM") info "termination requested" running_processes.each do |pid, process| - info "killing pid #{pid}", process + info "killing #{process.name} in pid #{pid}" Process.kill(signal, pid) end exit 0 end def info(message, process=nil) - puts "[foreman] [#{Time.now.utc}] [#{process ? process.name : "system"}] #{message}" + print process.color if process + print "[#{Time.now.strftime("%H:%M:%S")}] [#{process ? process.name : "system"}] #{message.chomp}" + print Term::ANSIColor.reset + puts end def print_info info "currently running processes:" running_processes.each do |pid, process| @@ -101,19 +114,23 @@ def read_procfile(procfile) File.read(procfile) end - def run_loop - while true - pid, status = Process.wait2 - process = running_processes.delete(pid) - info "exited with code #{status}", process - fork process - end + def watch_for_termination + pid, status = Process.wait2 + process = running_processes.delete(pid) + info "process terminated", process + kill_and_exit end def running_processes @running_processes ||= {} + end + + def next_color + @current_color ||= -1 + @current_color += 1 + @current_color >= COLORS.length ? "" : COLORS[@current_color] end end