require 'open3'
BUFFER_SIZE=1024 if(!defined?(BUFFER_SIZE))
# = Command
#
# execution of system commands
#
# = Keys
#
# - :input The input of the commands.
# - :timeout The timeout in seconds.
# a value of zero is to infinite timeout.
# defaults to zero
# - :directory The working directory for the command.
# defaults to the current directory
# - :exit_code The exit code of the command
# - :output The output contains the stdout output of the command
# - :error The error contains stderr output of the command
# - :machine The name of the machine the command executed on
# - :user The user name
# - :start_time
# - :end_time
#
class Command < Hash
def initialize command
self[:input] = ''
self[:timeout] = 0
self[:directory] = ''
self[:exit_code] = 0
self[:output] = ''
self[:error] = ''
self[:machine] = ''
self[:user] = ''
self[:start_time] = nil
self[:end_time] = nil
if(command.kind_of?(String))
self[:input] = command
end
if(command.kind_of?(Hash))
command.each{|k,v|
self[k.to_sym]=v
}
end
end
def quiet?
(self.has_key?(:quiet) && self[:quiet])
end
def execute value=nil
if(!value.nil? && value.is_a?(Hash))
value.each{|k,v|self[k]=v}
end
pwd=Dir.pwd
self[:directory] = pwd if(!self.has_key?(:directory) || self[:directory].length==0)
if(self[:timeout] > 0)
puts "#{self[:input]} (#{self[:directory]}) timeout #{self[:timeout].to_s}" if(!quiet?)
else
puts "#{self[:input]} (#{self[:directory]})" if(!quiet?)
end
self[:machine] = Command.machine
self[:user] = Command.user
self[:start_time]=Time.now
timer=Timer.new
Dir.chdir(self[:directory]) do
if self[:input].include?('<%') && self[:input].include?('%>')
ruby = self[:input].gsub("<%","").gsub("%>","")
begin
self[:output]=eval(ruby)
rescue
self[:exit_code]=1
self[:error]="unable to eval(#{ruby})"
end
self[:elapsed] = timer.elapsed_str
self[:end_time] = Time.now
else
begin
if(self[:timeout] <= 0)
self[:output],self[:error],status= Open3.capture3(self[:input])
self[:exit_code]=status.to_i
self[:elapsed] = timer.elapsed_str
self[:end_time] = Time.now
else
require_relative 'timeout.rb'
#puts run_with_timeout(self[:input], self[:timeout], 1).to_s
#self[:output] = run_with_timeout(self[:input], self[:timeout], 1)
result=run_with_timeout2(self[:directory],self[:input], self[:timeout], 2)
self[:output]=result[0]
self[:error]=result[1]
self[:exit_code]=result[2]
self[:elapsed] = timer.elapsed_str
self[:end_time] = Time.now
if(timer.elapsed >= self[:timeout])
self[:exit_code]=1
self[:error] = self[:error] + "timed out"
end
end
rescue Exception => e
self[:elapsed] = timer.elapsed_str
self[:end_time] = Time.now
self[:error] = "Exception: " + e.to_s
self[:exit_code]=1
end
end
end
if(self[:exit_code] != 0)
if(!quiet?)
puts "exit_code=#{self[:exit_code]}"
puts self[:output]
puts self[:error]
end
if(!self.has_key?(:ignore_failure) || !self[:ignore_failure])
raise "#{self[:input]} failed"
end #unless (self.has_key?(:ignore_failure) && self[:ignore_failure]==true)
end
end
def self.machine
if !ENV['COMPUTERNAME'].nil?
return ENV['COMPUTERNAME']
end
machine = `hostname`
machine = machine.split('.')[0] if machine.include?('.')
return machine.strip
end
def self.user
ENV['USER'].nil? ? ENV['USERNAME'] : ENV['USER']
end
def self.home
["USERPROFILE","HOME"].each {|v|
return ENV[v].gsub('\\','/') unless ENV[v].nil?
}
dir="~"
dir=ENV["HOME"] unless ENV["HOME"].nil?
dir=ENV["USERPROFILE"].gsub('\\','/') unless ENV["USERPROFILE"].nil?
return dir
end
def self.dev_root
["DEV_HOME","DEV_ROOT"].each {|v|
return ENV[v].gsub('\\','/') unless ENV[v].nil?
}
dir=home
#dir=ENV["DEV_ROOT"].gsub('\\','/') unless ENV["DEV_ROOT"].nil?
return dir
end
def self.exit_code command
cmd = Command.new(command)
cmd[:ignore_failure]=true
cmd[:quiet]=true
cmd.execute
cmd[:exit_code]
end
def self.output command
cmd = Command.new(command)
cmd[:ignore_failure]=true
cmd[:quiet]=true
cmd.execute
cmd[:output]
end
def getFormattedTimeSpan timespan
seconds = timespan
seconds.to_s + " sec"
end
def summary
duration=""
duration=getFormattedTimeSpan(self[:end_time]-[:start_time]) + " - " if(!self[:end_time].nil?)
duration + "#{self[:exit_code].to_s} #{self[:input]} (#{self[:directory]})"
end
def to_html
if self[:exit_code] == 0
[
'
'
].join
else
[
' | ',
self[:input],
' | ',
map { |k, v| ["#{k} | ", v.respond_to?(:to_html) ? v.to_html : "#{v} | "] },
' ',
' |
|
'
].join
end
end
end