class Nucleon::Util::Shell

Public Class Methods

connection(name = :core) click to toggle source
   # File lib/core/util/shell.rb
51 def self.connection(name = :core)
52   Nucleon.manager(@@supervisors, name, self)
53 end

Public Instance Methods

exec(command, options = {}, &code) click to toggle source
    # File lib/core/util/shell.rb
 63 def exec(command, options = {}, &code)
 64   config = Config.ensure(options)
 65   
 66   min   = config.get(:min, 1).to_i
 67   tries = config.get(:tries, min).to_i
 68   tries = ( min > tries ? min : tries )
 69   
 70   info_prefix  = config.get(:info_prefix, '')
 71   info_suffix  = config.get(:info_suffix, '')
 72   error_prefix = config.get(:error_prefix, '')
 73   error_suffix = config.get(:error_suffix, '')
 74   
 75   ui           = config.get(:ui, Nucleon.ui)
 76   
 77   conditions   = Nucleon.events(config.get(:exit, {}), true)
 78   
 79   $stdout.sync = true
 80   $stderr.sync = true
 81   
 82   system_result = Result.new(command)
 83   
 84   for i in tries.downto(1)
 85     logger.info(">> running shell: #{command}")
 86     
 87     begin
 88       t1, output_new, output_orig, output_reader = pipe_exec_stream($stdout, conditions, { 
 89         :prefix => info_prefix, 
 90         :suffix => info_suffix,
 91         :quiet  => config.get(:quiet, false) 
 92       }, 'output') do |data|
 93         system_result.append_output(data)
 94         code ? code.call(:output, command, data) : true
 95       end
 96       
 97       t2, error_new, error_orig, error_reader = pipe_exec_stream($stderr, conditions, { 
 98         :prefix => error_prefix, 
 99         :suffix => error_suffix,
100         :quiet  => config.get(:quiet, false)  
101       }, 'error') do |data|
102         system_result.append_errors(data)
103         code ? code.call(:error, command, data) : true
104       end
105       
106       system_success       = system(command)
107       system_result.status = $?.exitstatus
108       
109     ensure
110       output_success = close_exec_pipe(t1, $stdout, output_orig, output_new, 'output')
111       error_success  = close_exec_pipe(t2, $stderr, error_orig, error_new, 'error')
112     end
113     
114     unless config.get(:quiet, false)
115       logger.warn("`#{command}` messages: #{system_result.errors}") if system_result.errors.length > 0
116     end
117     logger.warn("`#{command}` status: #{system_result.status}") unless system_result.status == 0
118       
119     success = ( system_success && output_success && error_success )
120                 
121     min -= 1
122     break if success && min <= 0 && conditions.empty?
123   end
124   system_result
125 end
test_connection() click to toggle source
   # File lib/core/util/shell.rb
57 def test_connection
58   true
59 end

Protected Instance Methods

check_conditions(data, conditions, match_prefix = '', &code) click to toggle source
    # File lib/core/util/shell.rb
163 def check_conditions(data, conditions, match_prefix = '', &code)
164   prefix = ''
165   
166   unless ! conditions || conditions.empty?
167     conditions.each do |key, event|
168       if event.check(data)
169         prefix = match_prefix
170         conditions.delete(key)
171       end
172     end
173   end
174   
175   result = true
176   if code
177     result = code.call
178     
179     unless prefix.empty?
180       case result
181       when Hash
182         result[:prefix] = prefix
183       else
184         result = { :success => result, :prefix => prefix }
185       end
186     end
187   end
188   return result
189 end
close_exec_pipe(thread, output, original, write, label) click to toggle source
    # File lib/core/util/shell.rb
150 def close_exec_pipe(thread, output, original, write, label)
151   output.reopen(original)
152    
153   write.close
154   success = thread.value
155   
156   original.close
157   return success
158 end
pipe_exec_stream(output, conditions, options, label, &code) click to toggle source
    # File lib/core/util/shell.rb
129 def pipe_exec_stream(output, conditions, options, label, &code)
130   original     = output.dup
131   read, write  = IO.pipe
132   
133   match_prefix = ( options[:match_prefix] ? options[:match_prefix] : 'EXIT' )
134   
135   thread = process_stream(read, original, options, label) do |data|
136     check_conditions(data, conditions, match_prefix) do
137       code ? code.call(data) : true
138     end
139   end
140   
141   thread.abort_on_exception = false
142   
143   output.reopen(write)    
144   return thread, write, original, read
145 end
process_stream(input, output, options, label, &code) click to toggle source
    # File lib/core/util/shell.rb
194 def process_stream(input, output, options, label, &code)
195   return Thread.new do
196     success        = true      
197     default_prefix = ( options[:prefix] ? options[:prefix] : '' )
198     default_suffix = ( options[:suffix] ? options[:suffix] : '' )
199     
200     begin
201       while ( data = input.readpartial(1024) )
202         message = data.strip
203         newline = ( data[-1,1].match(/\n/) ? true : false )
204                                
205         unless message.empty?
206           lines = message.split(/\n/)
207           lines.each_with_index do |line, index|
208             prefix  = default_prefix
209             suffix  = default_suffix
210             
211             unless line.empty?
212               if code
213                 result = code.call(line)
214                                         
215                 if result && result.is_a?(Hash)
216                   prefix = result[:prefix]
217                   suffix = result[:suffix]
218                   result = result[:success]                 
219                 end
220                 success = result if success
221               end
222           
223               prefix = ( prefix && ! prefix.empty? ? prefix : '' )
224               suffix = ( suffix && ! suffix.empty? ? suffix : '' )            
225               eol    = ( index < lines.length - 1 || newline ? "\n" : ' ' )
226               
227               unless options[:quiet]
228                 output.write(prefix.lstrip + line + suffix.rstrip + eol)
229               end
230             end
231           end
232         end
233       end
234     rescue EOFError
235     end
236     
237     input.close()
238     success
239   end
240 end