require 'json' require 'open3' require 'stringio' require 'logger' # Optionally can specify the command to continue from # Exit on first failure # def time_diff_milli(start, finish) (finish - start) * 1000.0 end def handleIO(stillOpen, ioArray, io, log) if ioArray.include?(io) begin log.write(io.readpartial(4096)) rescue EOFError stillOpen.delete_if{|s| s == io} end end end class Audit def start (id, cmd) self.log( id, cmd, "start", "", 0, "") end def complete (id, cmd, status, msecs, result) self.log( id, cmd, "complete", status, msecs, result) end def status (id, cmd, status, msecs, result) data = { "message" => { "id" => id, "cmd" => cmd, "task" => "status", "status" => status, "elapsed" => msecs, "result" => result } } puts data.to_json File.open(Canzea::config[:logging_root] + '/audit.log', 'a') { |file| file.puts(data.to_json) } end def log (id, cmd, task, status, msecs, result) data = { "message" => { "id" => id, "cmd" => cmd, "task" => task, "status" => status, "elapsed" => msecs, "result" => result } } summary = { "message" => { "id" => id, "cmd" => cmd, "task" => task, "status" => status, "elapsed" => msecs } } puts summary.to_json File.open(Canzea::config[:logging_root] + '/audit.log', 'a') { |file| file.puts(data.to_json) } end end class RunnerWorker def run(command, start, lines, statusIndicator = false ) audit = Audit.new log = Logger.new(Canzea::config[:logging_root] + '/plans.log') log.info("HANDLING: " + command) l = command audit.start( "#{lines + 1 }", l.chomp) log.info("#{lines + 1} FOUND: " + l) t1 = Time.now Open3.popen3(ENV, l) {|stdin, stdout, stderr, wait_thr| pid = wait_thr.pid # pid of the started process. log_w = StringIO.new stillOpen = [stdout, stderr] while !stillOpen.empty? fhs = select(stillOpen, nil, nil, nil) handleIO(stillOpen, fhs[0], stdout, log_w) handleIO(stillOpen, fhs[0], stderr, log_w) end exit_status = wait_thr.value # wait for it to finish log_w.close_write output = log_w.string output.split(/\n/).each do | line | puts "-- #{line}" end puts "-- Exit Status = #{exit_status}" log.info("STDOUT #{output}") log.info("Exit Status = #{exit_status}") # if exit status is failure then exit right away t2 = Time.now msecs = time_diff_milli t1, t2 audit.complete("#{lines + 1}", l.chomp, exit_status.exitstatus, msecs, output) if (statusIndicator) audit.status("#{lines + 1}", l.chomp, exit_status.exitstatus, msecs, output) end if exit_status.exitstatus != 0 abort() end } lines += 1 return lines end end