class Pups::ExecCommand
Attributes
background[RW]
cd[R]
commands[R]
raise_on_fail[RW]
stdin[RW]
stop_signal[RW]
Public Class Methods
from_hash(hash, params)
click to toggle source
# File lib/pups/exec_command.rb, line 44 def self.from_hash(hash, params) cmd = new(params, hash['cd']) case c = hash['cmd'] when String then cmd.add(c) when Array then c.each { |i| cmd.add(i) } end cmd.background = hash['background'] cmd.stop_signal = hash['stop_signal'] || 'TERM' cmd.raise_on_fail = hash['raise_on_fail'] if hash.key? 'raise_on_fail' cmd.stdin = interpolate_params(hash['stdin'], params) cmd end
from_str(str, params)
click to toggle source
# File lib/pups/exec_command.rb, line 60 def self.from_str(str, params) cmd = new(params) cmd.add(str) cmd end
new(params, cd = nil)
click to toggle source
# File lib/pups/exec_command.rb, line 66 def initialize(params, cd = nil) @commands = [] @params = params @cd = interpolate_params(cd) @raise_on_fail = true end
terminate_async(opts = {})
click to toggle source
# File lib/pups/exec_command.rb, line 11 def self.terminate_async(opts = {}) return unless defined? @@asyncs Pups.log.info('Terminating async processes') @@asyncs.each do |async| Pups.log.info("Sending #{async[:stop_signal]} to #{async[:command]} pid: #{async[:pid]}") begin Process.kill(async[:stop_signal], async[:pid]) rescue StandardError nil end end @@asyncs.map do |async| Thread.new do Timeout.timeout(opts[:wait] || 10) do Process.wait(async[:pid]) rescue StandardError nil end rescue Timeout::Error Pups.log.info("#{async[:command]} pid:#{async[:pid]} did not terminate cleanly, forcing termination!") begin Process.kill('KILL', async[:pid]) Process.wait(async[:pid]) rescue Errno::ESRCH rescue Errno::ECHILD end end end.each(&:join) end
Public Instance Methods
add(cmd)
click to toggle source
# File lib/pups/exec_command.rb, line 73 def add(cmd) @commands << process_params(cmd) end
process_params(cmd)
click to toggle source
# File lib/pups/exec_command.rb, line 123 def process_params(cmd) processed = interpolate_params(cmd) @cd ? "cd #{cd} && #{processed}" : processed end
run()
click to toggle source
# File lib/pups/exec_command.rb, line 77 def run commands.each do |command| Pups.log.info("> #{command}") pid = spawn(command) Pups.log.info(@result.readlines.join("\n")) if @result pid end rescue StandardError raise if @raise_on_fail end
spawn(command)
click to toggle source
# File lib/pups/exec_command.rb, line 88 def spawn(command) if background pid = Process.spawn(command) (@@asyncs ||= []) << { pid: pid, command: command, stop_signal: (stop_signal || 'TERM') } Thread.new do begin Process.wait(pid) rescue Errno::ECHILD # already exited so skip end @@asyncs.delete_if { |async| async[:pid] == pid } end return pid end IO.popen(command, 'w+') do |f| if stdin # need a way to get stdout without blocking Pups.log.info(stdin) f.write stdin f.close else Pups.log.info(f.readlines.join) end end unless $CHILD_STATUS == 0 err = Pups::ExecError.new("#{command} failed with return #{$CHILD_STATUS.inspect}") err.exit_code = $CHILD_STATUS.exitstatus raise err end nil end