class DTK::Agent::Command
This is container for command as received from Node Agent
Constants
- STDOUT_REDIRECT
command - string to be run on system, e.g. ifconfig type - type of command e.g. syscall, ruby if - callback to be run if exit status is = 0 unless - callback to be run if exit status is != 0 stdout_redirect - redirect all output to stdout
- STREAM_TIMEOUT
Attributes
backtrace[RW]
command[RW]
command_type[RW]
process[RW]
Public Class Methods
new(value_hash)
click to toggle source
# File lib/command.rb, line 28 def initialize(value_hash) @command_type = value_hash['type'] @command = value_hash['command'] @stdout_redirect = !!value_hash['stdout_redirect'] @if = value_hash['if'] @unless = value_hash['unless'] @timeout = (value_hash['timeout'] || 0).to_i @env_vars = value_hash['env_vars'] if @if && @unless Log.warn "Unexpected case, both if/unless conditions have been set for command #{@command}(#{@command_type})" end end
Public Instance Methods
callback_pending?()
click to toggle source
Checks if there is callaback present, callback beeing if/unless command
# File lib/command.rb, line 73 def callback_pending? @if || @unless end
err()
click to toggle source
# File lib/command.rb, line 126 def err return @error_message if @error_message @err.encode!('UTF-8', :invalid => :replace, :undef => :replace, :replace => '') end
exited?()
click to toggle source
# File lib/command.rb, line 106 def exited? return true if @error_message @process_status.exited? end
exitstatus()
click to toggle source
# File lib/command.rb, line 116 def exitstatus return 1 if @error_message @process_status.exitstatus end
is_positioning?()
click to toggle source
# File lib/command.rb, line 77 def is_positioning? 'file'.eql?(@command_type) end
out()
click to toggle source
# File lib/command.rb, line 121 def out return '' if @error_message @out.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => '') end
run_condition_task()
click to toggle source
Returns true/false based on condition data and result of process
# File lib/command.rb, line 84 def run_condition_task condition_command = @if condition_command ||= @unless # this is needed since Timeout block will not allow initialization of new variables condition_process_status = nil begin Timeout.timeout(@timeout) do _out, _err, condition_process_status = Open3.capture3(condition_command) end rescue Exception => e # do not log error in cases it was expected. Meaning that 'unless' condition was set. Log.warn("Condition command '#{condition_command}' ran into an exception, message: #{e.message}") unless @unless # return true if unless condition was used return @unless ? true : false end return condition_process_status.exitstatus > 0 ? false : true if @if return condition_process_status.exitstatus > 0 ? true : false if @unless end
start_task()
click to toggle source
Creates Posix Spawn of given process
# File lib/command.rb, line 48 def start_task begin Commander.set_environment_variables(@env_vars) results = capture3_with_timeout(formulate_command) @out = results[:stdout] @err = results[:stderr] @process_status = results[:status] @error_message = "Timeout (#{@timeout} sec) for this action has been exceeded" if results[:timeout] rescue Exception => e @error_message = e.message @backtrace = e.backtrace Log.error(@error_message, @backtrace) ensure Commander.clear_environment_variables(@env_vars) end end
started?()
click to toggle source
# File lib/command.rb, line 111 def started? return true if @error_message !!@process_status end
to_s()
click to toggle source
# File lib/command.rb, line 131 def to_s "#{formulate_command} (#{command_type})" end
Private Instance Methods
capture3_with_timeout(*cmd)
click to toggle source
Open3 method extended with timeout, more info gist.github.com/pasela/9392115
# File lib/command.rb, line 141 def capture3_with_timeout(*cmd) spawn_opts = Hash === cmd.last ? cmd.pop.dup : {} opts = { :stdin_data => "", :timeout => @timeout, :signal => :TERM, :kill_after => nil, } in_r, in_w = IO.pipe out_r, out_w = IO.pipe err_r, err_w = IO.pipe in_w.sync = true spawn_opts[:in] = in_r spawn_opts[:out] = out_w spawn_opts[:err] = err_w result = { :pid => nil, :status => nil, :stdout => nil, :stderr => nil, :timeout => false, } out_reader = nil err_reader = nil wait_thr = nil begin Timeout.timeout(opts[:timeout]) do result[:pid] = spawn(*cmd, spawn_opts) wait_thr = Process.detach(result[:pid]) in_r.close out_w.close err_w.close out_reader = Thread.new { out_r.read } err_reader = Thread.new { err_r.read } in_w.close result[:status] = wait_thr.value end rescue Timeout::Error result[:timeout] = true pid = result[:pid] Process.kill(opts[:signal], pid) if opts[:kill_after] unless wait_thr.join(opts[:kill_after]) Process.kill(:KILL, pid) end end ensure result[:status] = wait_thr.value if wait_thr begin # there is a bug where there is infinite leg on out_reader (e.g. hohup) commands Timeout.timeout(STREAM_TIMEOUT) do result[:stdout] = out_reader.value if out_reader result[:stderr] = err_reader.value if err_reader end rescue Timeout::Error result[:stdout] ||= '' result[:stderr] ||= '' end out_r.close unless out_r.closed? err_r.close unless err_r.closed? end result end
formulate_command()
click to toggle source
Based on stdout-redirect flag
# File lib/command.rb, line 217 def formulate_command @command end