shexecutor 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +25 -0
 - data/lib/shexecutor/version.rb +1 -1
 - data/lib/shexecutor.rb +32 -13
 - data/spec/executor_spec.rb +13 -2
 - metadata +1 -1
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: c90615e32be8148e01050f014d0bf7e107b403ad
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 55607d1521893564995bea9da74153b084bd92ec
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 54788b1980134c365b3b4c8cfb20c0d73ad74b3283e398f86e2b24662c57fcc382978dec80dfe10f463cf730ab7bab1244475dd1a32c609988a70ed888204b9d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: becd1258cd4c5c1a526f180a419503430d5549c4064df9078300ba102d4100fb9229df812b6ca5b79787ec4d94894d00eea7ff993ed7bbd6073de8474f991af9
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -20,6 +20,31 @@ For a full description of status, please see Process::Status 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            This gem is sponsored by Hetzner (Pty) Ltd - http://hetzner.co.za
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            ## Initialization options:
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            Required / optional:
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            ```
         
     | 
| 
      
 28 
     | 
    
         
            +
              {
         
     | 
| 
      
 29 
     | 
    
         
            +
                :application_path                     # Path of the command to run
         
     | 
| 
      
 30 
     | 
    
         
            +
                :params                               # Parameters to pass the command
         
     | 
| 
      
 31 
     | 
    
         
            +
              }
         
     | 
| 
      
 32 
     | 
    
         
            +
            ```
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            ```
         
     | 
| 
      
 35 
     | 
    
         
            +
              @@default_options = {
         
     | 
| 
      
 36 
     | 
    
         
            +
                :timeout => -1,                     # Seconds after which to raise Timeout::Error if not completed
         
     | 
| 
      
 37 
     | 
    
         
            +
                :protect_against_injection => true, # look for spaces in and tainted application path
         
     | 
| 
      
 38 
     | 
    
         
            +
                :stdout_path => nil,                # file to append stdout to
         
     | 
| 
      
 39 
     | 
    
         
            +
                :stderr_path => nil,                # file to append stderr to
         
     | 
| 
      
 40 
     | 
    
         
            +
                :append_stdout_path => true,        # if true, will append, otherwise will overwrite
         
     | 
| 
      
 41 
     | 
    
         
            +
                :append_stderr_path => true,        # if true, will append, otherwise will overwrite
         
     | 
| 
      
 42 
     | 
    
         
            +
                :replace => false,                  # replace the running process with the command
         
     | 
| 
      
 43 
     | 
    
         
            +
                :wait_for_completion => false,      # block until the command completes
         
     | 
| 
      
 44 
     | 
    
         
            +
                :timeout_sig_kill_retry => 500      # if timeout occurs, send TERM, and send signal 9 if still present after X ms
         
     | 
| 
      
 45 
     | 
    
         
            +
              }
         
     | 
| 
      
 46 
     | 
    
         
            +
            ```
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
       23 
48 
     | 
    
         
             
            ## Installation
         
     | 
| 
       24 
49 
     | 
    
         | 
| 
       25 
50 
     | 
    
         
             
            Add this line to your application's Gemfile:
         
     | 
    
        data/lib/shexecutor/version.rb
    CHANGED
    
    
    
        data/lib/shexecutor.rb
    CHANGED
    
    | 
         @@ -3,14 +3,15 @@ require 'open3' 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module SHExecutor
         
     | 
| 
       5 
5 
     | 
    
         
             
              @@default_options = {
         
     | 
| 
       6 
     | 
    
         
            -
                :timeout => -1,
         
     | 
| 
       7 
     | 
    
         
            -
                :protect_against_injection => true,
         
     | 
| 
       8 
     | 
    
         
            -
                :stdout_path => nil,
         
     | 
| 
       9 
     | 
    
         
            -
                :stderr_path => nil,
         
     | 
| 
       10 
     | 
    
         
            -
                :append_stdout_path => true,
         
     | 
| 
       11 
     | 
    
         
            -
                :append_stderr_path => true,
         
     | 
| 
       12 
     | 
    
         
            -
                :replace => false,
         
     | 
| 
       13 
     | 
    
         
            -
                :wait_for_completion => false
         
     | 
| 
      
 6 
     | 
    
         
            +
                :timeout => -1,                     # Seconds after which to raise Timeout::Error if not completed
         
     | 
| 
      
 7 
     | 
    
         
            +
                :protect_against_injection => true, # look for spaces in and tainted application path
         
     | 
| 
      
 8 
     | 
    
         
            +
                :stdout_path => nil,                # file to append stdout to
         
     | 
| 
      
 9 
     | 
    
         
            +
                :stderr_path => nil,                # file to append stderr to
         
     | 
| 
      
 10 
     | 
    
         
            +
                :append_stdout_path => true,        # if true, will append, otherwise will overwrite
         
     | 
| 
      
 11 
     | 
    
         
            +
                :append_stderr_path => true,        # if true, will append, otherwise will overwrite
         
     | 
| 
      
 12 
     | 
    
         
            +
                :replace => false,                  # replace the running process with the command
         
     | 
| 
      
 13 
     | 
    
         
            +
                :wait_for_completion => false,      # block until the command completes
         
     | 
| 
      
 14 
     | 
    
         
            +
                :timeout_sig_kill_retry => 500      # if timeout occurs, send TERM, and send signal 9 if still present after X ms
         
     | 
| 
       14 
15 
     | 
    
         
             
              }
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
              def self.default_options
         
     | 
| 
         @@ -127,9 +128,9 @@ module SHExecutor 
     | 
|
| 
       127 
128 
     | 
    
         
             
                def run_process(application_path, options = "")
         
     | 
| 
       128 
129 
     | 
    
         
             
                  data_out = StringIO.new
         
     | 
| 
       129 
130 
     | 
    
         
             
                  data_err = StringIO.new
         
     | 
| 
       130 
     | 
    
         
            -
                  t0 = nil
         
     | 
| 
      
 131 
     | 
    
         
            +
                  @t0 = nil
         
     | 
| 
       131 
132 
     | 
    
         
             
                  Open3::popen3(application_path, options) do |stdin, stdout, stderr, thr|
         
     | 
| 
       132 
     | 
    
         
            -
                    t0 = thr
         
     | 
| 
      
 133 
     | 
    
         
            +
                    @t0 = thr
         
     | 
| 
       133 
134 
     | 
    
         
             
                    # read srderr and stdout into buffers to prevent blocking
         
     | 
| 
       134 
135 
     | 
    
         
             
                    t1 = Thread.new do
         
     | 
| 
       135 
136 
     | 
    
         
             
                      IO.copy_stream(stdout, data_out)
         
     | 
| 
         @@ -151,7 +152,7 @@ module SHExecutor 
     | 
|
| 
       151 
152 
     | 
    
         
             
                    t1.join if not should_timeout?
         
     | 
| 
       152 
153 
     | 
    
         
             
                    t2.join if not should_timeout?
         
     | 
| 
       153 
154 
     | 
    
         
             
                  end
         
     | 
| 
       154 
     | 
    
         
            -
                  return data_out, data_err, t0
         
     | 
| 
      
 155 
     | 
    
         
            +
                  return data_out, data_err, @t0
         
     | 
| 
       155 
156 
     | 
    
         
             
                end
         
     | 
| 
       156 
157 
     | 
    
         | 
| 
       157 
158 
     | 
    
         
             
                def block_process
         
     | 
| 
         @@ -170,17 +171,35 @@ module SHExecutor 
     | 
|
| 
       170 
171 
     | 
    
         
             
                    @result.join
         
     | 
| 
       171 
172 
     | 
    
         
             
                    @result.value
         
     | 
| 
       172 
173 
     | 
    
         
             
                  rescue Timeout::Error => ex
         
     | 
| 
      
 174 
     | 
    
         
            +
                    kill_process(@t0.pid)
         
     | 
| 
       173 
175 
     | 
    
         
             
                    raise ex
         
     | 
| 
       174 
176 
     | 
    
         
             
                  end
         
     | 
| 
       175 
177 
     | 
    
         
             
                end
         
     | 
| 
       176 
178 
     | 
    
         | 
| 
      
 179 
     | 
    
         
            +
                def process?(pid)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 181 
     | 
    
         
            +
                    Process.getpgid(pid)
         
     | 
| 
      
 182 
     | 
    
         
            +
                    true
         
     | 
| 
      
 183 
     | 
    
         
            +
                  rescue Errno::ESRCH
         
     | 
| 
      
 184 
     | 
    
         
            +
                    false
         
     | 
| 
      
 185 
     | 
    
         
            +
                  end
         
     | 
| 
      
 186 
     | 
    
         
            +
                end
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                def kill_process(pid)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  return if pid.nil?
         
     | 
| 
      
 190 
     | 
    
         
            +
                  Process.kill("TERM", pid)
         
     | 
| 
      
 191 
     | 
    
         
            +
                  count = 0
         
     | 
| 
      
 192 
     | 
    
         
            +
                  while (count < (@options[:timeout_sig_kill_retry]/100) and process?(pid)) do
         
     | 
| 
      
 193 
     | 
    
         
            +
                    sleep 0.1
         
     | 
| 
      
 194 
     | 
    
         
            +
                  end
         
     | 
| 
      
 195 
     | 
    
         
            +
                  Process.kill(9, pid) if process?(pid)
         
     | 
| 
      
 196 
     | 
    
         
            +
                end
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
       177 
198 
     | 
    
         
             
                def fork_process
         
     | 
| 
       178 
199 
     | 
    
         
             
                  validate
         
     | 
| 
       179 
200 
     | 
    
         
             
                  @stdin_stream, @stdout_stream, @stderr_stream, @result = Open3::popen3(@options[:application_path], *@options[:params]) 
         
     | 
| 
       180 
201 
     | 
    
         
             
                end
         
     | 
| 
       181 
202 
     | 
    
         | 
| 
       182 
     | 
    
         
            -
                private
         
     | 
| 
       183 
     | 
    
         
            -
             
     | 
| 
       184 
203 
     | 
    
         
             
                def should_timeout?
         
     | 
| 
       185 
204 
     | 
    
         
             
                  @options[:timeout] > 0
         
     | 
| 
       186 
205 
     | 
    
         
             
                end
         
     | 
    
        data/spec/executor_spec.rb
    CHANGED
    
    | 
         @@ -27,7 +27,8 @@ describe 'Executor' do 
     | 
|
| 
       27 
27 
     | 
    
         
             
                    :append_stdout_path => false,
         
     | 
| 
       28 
28 
     | 
    
         
             
                    :append_stderr_path => false,
         
     | 
| 
       29 
29 
     | 
    
         
             
                    :replace => false,
         
     | 
| 
       30 
     | 
    
         
            -
                    :wait_for_completion => true
         
     | 
| 
      
 30 
     | 
    
         
            +
                    :wait_for_completion => true,
         
     | 
| 
      
 31 
     | 
    
         
            +
                    :timeout_sig_kill_retry => 500
         
     | 
| 
       31 
32 
     | 
    
         
             
                  }
         
     | 
| 
       32 
33 
     | 
    
         
             
                  @iut = SHExecutor::Executor.new(iut_options)
         
     | 
| 
       33 
34 
     | 
    
         
             
                  expect(@iut.options).to eq(iut_options)
         
     | 
| 
         @@ -207,7 +208,7 @@ describe 'Executor' do 
     | 
|
| 
       207 
208 
     | 
    
         
             
              end
         
     | 
| 
       208 
209 
     | 
    
         | 
| 
       209 
210 
     | 
    
         
             
              context 'when asked to execute and block' do
         
     | 
| 
       210 
     | 
    
         
            -
                it 'should raise a  
     | 
| 
      
 211 
     | 
    
         
            +
                it 'should raise a Timeout::Error if a timeout is specified and the process does not exit before' do
         
     | 
| 
       211 
212 
     | 
    
         
             
                  test_command = "/bin/sleep"
         
     | 
| 
       212 
213 
     | 
    
         
             
                  test_params = ["5"]
         
     | 
| 
       213 
214 
     | 
    
         
             
                  iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
         
     | 
| 
         @@ -219,6 +220,16 @@ describe 'Executor' do 
     | 
|
| 
       219 
220 
     | 
    
         
             
                  expect(after - before).to be < 2.1
         
     | 
| 
       220 
221 
     | 
    
         
             
                end
         
     | 
| 
       221 
222 
     | 
    
         | 
| 
      
 223 
     | 
    
         
            +
                it 'should kill the subprocess when a TimeoutError is raised' do
         
     | 
| 
      
 224 
     | 
    
         
            +
                  test_command = "/bin/sleep"
         
     | 
| 
      
 225 
     | 
    
         
            +
                  test_params = ["2"]
         
     | 
| 
      
 226 
     | 
    
         
            +
                  iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
         
     | 
| 
      
 227 
     | 
    
         
            +
                  expect(Process).to receive(:kill)
         
     | 
| 
      
 228 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 229 
     | 
    
         
            +
                    iut.execute
         
     | 
| 
      
 230 
     | 
    
         
            +
                  }.to raise_error(Timeout::Error, "execution expired")
         
     | 
| 
      
 231 
     | 
    
         
            +
                end
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
       222 
233 
     | 
    
         
             
                it 'should call run_process with the command and parameters specified' do
         
     | 
| 
       223 
234 
     | 
    
         
             
                  test_command = "/bin/ls"
         
     | 
| 
       224 
235 
     | 
    
         
             
                  test_params = ["/tmp/"]
         
     |