Reputation: 5721
I want to test that a process is working so I run:
cmd = "my unix command"
results = `#{cmd}`
How can I add a timeout to the command so that if it takes more than x seconds I can assume that it is not working?
Upvotes: 4
Views: 2436
Reputation: 3711
One caveat to the previous answers, if the child process is using sudo
, then you cannot kill the child, and you will create zombie processes.
You will need to periodically run Process::waitpid(-1, Process::WNOHANG)
to collect the exit status for the children and clean up the process tables (thus cleaning up the zombies).
Upvotes: 0
Reputation: 31
Much simpler way with thread:
p = Thread.new{
#exec here
}
if p.join( period_in_seconds ).nil? then
#here thread p is still working
p.kill
else
#here thread p completed before 'period_in_seconds'
end
Upvotes: 0
Reputation: 80065
Ruby ships witrh the Timeout module.
require 'timeout'
res = ""
status = Timeout::timeout(5) {res = `#{cmd}`} rescue Timeout::Error
# a bit of experimenting:
res = nil
status = Timeout::timeout(1) {res = `sleep 2`} rescue Timeout::Error
p res # nil
p status # Timeout::Error
res = nil
status = Timeout::timeout(3) {res = `sleep 2`} rescue Timeout::Error
p res # ""
p status # ""
Upvotes: 9
Reputation: 198304
Put it in a thread, have another thread sleep for x seconds then kill the first one if it's not done yet.
process_thread = Thread.new do
`sleep 6` # the command you want to run
end
timeout_thread = Thread.new do
sleep 4 # the timeout
if process_thread.alive?
process_thread.kill
$stderr.puts "Timeout"
end
end
process_thread.join
timeout_thread.kill
steenslag's is nicer though :) This is the low-tech route.
Upvotes: 1