ruby process timeout terminate

ruby - tiempos de espera de rubí y comandos del sistema



process timeout (4)

Creo que tienes que kill manualmente:

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'' end rescue Timeout::Error puts ''process not finished in time, killing it'' Process.kill(''TERM'', pid) end

Tengo un tiempo de espera de rubí que llama a un comando del sistema (bash) como este ...

Timeout::timeout(10) { `my_bash_command -c12 -o text.txt` }

pero creo que incluso si se interrumpe el hilo de rubí, el comando real sigue ejecutándose en segundo plano ... ¿es normal? ¿Cómo puedo matarlo?


El manejo de procesos, señales y temporizadores no es muy fácil. Es por eso que podría considerar delegar esta tarea: use el timeout de timeout del comando en las nuevas versiones de Linux:

timeout --kill-after 5s 10s my_bash_command -c12 -o text.txt


Quizás esto ayude a alguien más que busca lograr una funcionalidad de tiempo de espera similar, pero necesita recopilar la salida del comando de shell.

He adaptado el método de @shurikk para trabajar con Ruby 2.0 y algunos códigos del proceso hijo de Fork con tiempo de espera y captura de salida para recopilar la salida.

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


para detener adecuadamente el árbol de proceso generado (no solo el proceso padre), se debe considerar algo como esto:

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 end end

Esto también le permite hacer un seguimiento del estado del proceso