class BoxGrinder::ExecHelper
Public Class Methods
new(options = {})
click to toggle source
# File lib/boxgrinder-core/helpers/exec-helper.rb, line 33 def initialize(options = {}) @log = options[:log] || Logger.new(STDOUT) end
Public Instance Methods
execute(command, options = {})
click to toggle source
# File lib/boxgrinder-core/helpers/exec-helper.rb, line 37 def execute(command, options = {}) redacted = options[:redacted] || [] redacted_command = command redacted.each { |word| redacted_command = redacted_command.gsub(word, '<REDACTED>') } @log.debug "Executing command: '#{redacted_command}'" output = "" # dirty workaround for ruby segfaults related to logger.rb STDOUT.sync = true STDERR.sync = true begin pid, stdin, stdout, stderr = (RUBY_PLATFORM =~ /java/ ? IO : Open4).send(:popen4, command) threads = [] threads << Thread.new(stdout) do |out| out.each do |l| l.chomp! l.strip! output << "\n#{l}" @log.debug l end end threads << Thread.new(stderr) do |err| err.each do |l| l.chomp! l.strip! output << "\n#{l}" @log.debug l end end threads.each { |t| t.join } # Assume the process exited cleanly, which can cause some bad behaviour, but I don't see better way # to get reliable status for processes both on MRI and JRuby # # http://jira.codehaus.org/browse/JRUBY-5673 status = AStruct.new(:exitstatus => 0) fakepid, status = Process.waitpid2(pid) if process_alive?(pid) raise "process exited with wrong exit status: #{status.exitstatus}" if !(RUBY_PLATFORM =~ /java/) and status.exitstatus != 0 return output.strip rescue Interrupt raise InterruptionError.new(pid), "Program was interrupted." rescue => e @log.error e.backtrace.join($/) raise "An error occurred while executing command: '#{redacted_command}', #{e.message}" end end
process_alive?(pid)
click to toggle source
# File lib/boxgrinder-core/helpers/exec-helper.rb, line 96 def process_alive?(pid) begin Process.getpgid(pid) true rescue Errno::ESRCH false end end