ruby timeouts and system commands ruby timeouts and system commands ruby ruby

ruby timeouts and system commands


I think you have to kill it manually:

require 'timeout'puts 'starting process'pid = Process.spawn('sleep 20')begin  Timeout.timeout(5) do    puts 'waiting for the process to end'    Process.wait(pid)    puts 'process finished in time'  endrescue Timeout::Error  puts 'process not finished in time, killing it'  Process.kill('TERM', pid)end


in order to properly stop spawned process tree (not just the parent process) one should consider something like this:

def exec_with_timeout(cmd, timeout)  pid = Process.spawn(cmd, {[:err,:out] => :close, :pgroup => true})  begin    Timeout.timeout(timeout) do      Process.waitpid(pid, 0)      $?.exitstatus == 0    end  rescue Timeout::Error    Process.kill(15, -Process.getpgid(pid))    false  endend

this also allows you to track process status


Perhaps this will help someone else looking to achieve similar timeout functionality, but needs to collect the output from the shell command.

I've adapted @shurikk's method to work with Ruby 2.0 and some code from Fork child process with timeout and capture output to collect the output.

def exec_with_timeout(cmd, timeout)  begin    # stdout, stderr pipes    rout, wout = IO.pipe    rerr, werr = IO.pipe    stdout, stderr = nil    pid = Process.spawn(cmd, pgroup: true, :out => wout, :err => werr)    Timeout.timeout(timeout) do      Process.waitpid(pid)      # close write ends so we can read from them      wout.close      werr.close      stdout = rout.readlines.join      stderr = rerr.readlines.join    end  rescue Timeout::Error    Process.kill(-9, pid)    Process.detach(pid)  ensure    wout.close unless wout.closed?    werr.close unless werr.closed?    # dispose the read ends of the pipes    rout.close    rerr.close  end  stdout end