# Executing a system command and stopping it after a specified

**URL:** <https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043>\
**Category:** Ruby\
**Created:** [April 15, 2007, 6:58am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043 "2007-04-15T06:58:25Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 15, 2007, 6:58am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/1 "2007-04-15T06:58:25Z")

</div>

I’d like to run a system command and then stop it after specified  
amount of time (in seconds or milliseconds.) What’s the best way to  
do it?

e.g.

exec(“cat /dev/video \> test.mpg”)

then kill the process after so many minutes, seconds, etc…

Also, if there is a better Ruby way to do this other than “cat”, I’m  
all ears…

Thanks.

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 15, 2007, 9:05am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/2 "2007-04-15T09:05:38Z")

</div>

On Apr 14, 9:57 pm, Robert La Ferla [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’d like to run a system command and then stop it after specified  
> amount of time (in seconds or milliseconds.) What’s the best way to  
> do it?

In Perl it was done by setting the signal ALRM (or using the “alarm”  
command). I’m not sure how this is done in Ruby as I haven’t had a  
use for signal trapping since using Ruby.

> Also, if there is a better Ruby way to do this other than “cat”, I’m  
> all ears…

# assuming binary file (i.e. mpg)

File.open(“/dev/video”, “rb”) do |inf|  
File.open(“test.mpg”, “wb”) do |outf|  
inf.each\_byte {|byte| outf.putc byte}  
end  
end

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 15, 2007, 9:09am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/3 "2007-04-15T09:09:38Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

Robert La Ferla wrote:

> ears…
> 
> Thanks.

# from “ri Timeout”:

require ‘timeout’  
status = Timeout::timeout(500) {  
exec(“cat /dev/video \> test.mpg”)  
}

Dan  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.6 (GNU/Linux)  
Comment: Using GnuPG with Mozilla - [http://enigmail.mozdev.org](http://enigmail.mozdev.org)

iD8DBQFGId0kUYnvW+YuEvYRAkc0AKDBBveie/L0/2ePNqkLKYKvqz4fTACgso+d  
g3U+yVpF+5pFf3RnGb+fS9o=  
=B+zE  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 15, 2007, 9:15am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/4 "2007-04-15T09:15:38Z")

</div>

On Apr 14, 9:57 pm, Robert La Ferla [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’d like to run a system command and then stop it after specified  
> amount of time (in seconds or milliseconds.) What’s the best way to  
> do it?

Out of curiosity I probed deeper and it looks like you’re looking for  
Timeout#timeout (see RDoc/ri for more information). Here is an  
example:

require ‘timeout’

# raises an exception if timeout is met

begin  
Timeout::timeout(5) { sleep 10 }  
rescue Timeout::Error  
puts “It timed out!”  
end

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 16, 2007, 2:31am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/5 "2007-04-16T02:31:27Z")

</div>

On Apr 15, 2007, at 3:39 AM, Stefan M. wrote:

> end  
> File.open(“test.mpg”, “wb”) do |output|  
> input.each\_byte {|byte| output.putc(byte)}  
> end  
> end  
> end  
> rescue Timeout::Error  
> puts(“Done”)  
> end

Thanks.

A couple of issues:

1. The time out is working but the “cat” process is not terminated.  
I tried both system(cmd) and `#{cmd}`.

2. I wonder if Ruby is fast enough to read /dev/video and dump it to  
a file without a delay. Imagine if this is running for a couple of  
hours…

BTW - My configuration is:

% ruby --version  
ruby 1.8.5 (2007-03-13 patchlevel 35) [i386-linux]

Fedora Linux 2.6.20-1.2933.fc6

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 15, 2007, 9:39am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/6 "2007-04-15T09:39:40Z")

</div>

Robert La Ferla wrote:

> I’d like to run a system command and then stop it after specified amount  
> of time (in seconds or milliseconds.) What’s the best way to do it?
> 
> e.g.
> 
> exec(“cat /dev/video \> test.mpg”)
> 
> then kill the process after so many minutes, seconds, etc…

Once you call exec the ruby program does not run anymore.

From the description of Kernel#exec  
[http://www.ruby-doc.org/core/classes/Kernel.html#M005957](http://www.ruby-doc.org/core/classes/Kernel.html#M005957)

Replaces the current process by running the given external command. If  
exec is given a single argument, that argument is taken as a line that  
is subject to shell expansion before being executed.

you may want to use

system(“cmd”) [module Kernel - RDoc Documentation](http://www.ruby-doc.org/core/classes/Kernel.html#M005960)  
`cmd` [module Kernel - RDoc Documentation](http://www.ruby-doc.org/core/classes/Kernel.html#M005979)  
%x { cmd }

wrapped in timeout

> Also, if there is a better Ruby way to do this other than “cat”, I’m all  
> ears…

I’m using `mencoder ...` with options set via string substitution to  
record TV-series

channel = ARGV[0]  
outfilename = ARGV[1]  
duration = ARGV[2]

`mencoder dvb://#{channel} -vf lavcdeint -o #{outfilename} -endpos #{duration} -oac lavc -ovc lavc -lavcopts acodec=mp2:vcodec=mpeg2video:vhq:vbitrate=2048`

If you want to read from ‘/dev/video’ you could combine james.d.masters  
and Dan Z.s suggestions - but using system or `

require “timeout”  
begin  
Timeout::timeout(600) do  
system(“cat /dev/video \> test.mpg”)  
# `cat /dev/video > test.mpg`  
end  
rescue Timeout::Error  
puts(“Done”)  
end

or

require “timeout”  
begin  
Timeout::timeout(600) do  
File.open(“/dev/video”, “rb”) do |input|  
File.open(“test.mpg”, “wb”) do |output|  
input.each\_byte {|byte| output.putc(byte)}  
end  
end  
end  
rescue Timeout::Error  
puts(“Done”)  
end

Stefan

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 16, 2007, 5:01am UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/7 "2007-04-16T05:01:34Z")

</div>

On Apr 15, 5:30 pm, Robert La Ferla [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 1. The time out is working but the “cat” process is not terminated.  
> I tried both system(cmd) and `#{cmd}`.

Maybe you will need to call the “kill” command… I’m not sure if  
child processes die with an exception being raised or not.

In any case, I’d use the alternatives mentioned here instead of using  
“system”. They are cleaner IMHO.

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 16, 2007, 12:21pm UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/8 "2007-04-16T12:21:11Z")

</div>

On Apr 15, 5:57 am, Robert La Ferla [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’d like to run a system command and then stop it after specified  
> amount of time (in seconds or milliseconds.) What’s the best way to  
> do it?

I have this handy function ; it raises an exception on timeout/non  
zero exit status, returns the result of the call  
otherwise (ie. what the process output on $stdout). In case of timeout  
it also attemts to kill the process (runs on Unix - no clue about  
other platforms!) :

# 

# Usage example :

# 

files = run(‘find -mtime -7’)

# 

# Function :

# 

def run(s, maxt = 10\*60)  
begin  
pipe = IO.popen(s, ‘r’)  
rescue Exception =\> e  
$stderr \<\< ‘Execution of ‘+s+’ has failed :’ + e.to\_s  
raise “run failed”  
end

begin  
Timeout::timeout(maxt) do |t|  
a = Process.waitpid2(pipe.pid)  
if a[1].exitstatus != 0  
$stderr \<\< 'Error while executing ’ + s  
raise “run failed”  
end  
end  
rescue Timeout::Error =\> e  
$stderr \<\< ‘Execution of ‘+s+’ has timed out. Killing subprocess’  
begin  
Process.kill(‘KILL’, pipe.pid)  
pipe.close  
rescue Object =\> e  
$stderr \<\< 'Failed killing process : ’ + e.to\_s  
end  
raise “run failed”  
end

out = pipe.gets(nil)  
pipe.close  
out  
end

I’ve edited it a bit to remove some of my specific dependencies - so  
there might be typos here 🙂  
It could be improved to also return the content of $stderr in case of  
non-zero exit status.

Anselm

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [April 16, 2007, 8:36pm UTC](https://www.ruby-forum.com/t/executing-a-system-command-and-stopping-it-after-a-specified/92043/9 "2007-04-16T20:36:24Z")

</div>

On Mon, 16 Apr 2007, Robert La Ferla wrote:

> > system(“cat /dev/video \> test.mpg”)  
> > Timeout::timeout(600) do  
> > Thanks.  
> > BTW - My configuration is:
> 
> % ruby --version  
> ruby 1.8.5 (2007-03-13 patchlevel 35) [i386-linux]
> 
> Fedora Linux 2.6.20-1.2933.fc6

require ‘rubygems’  
require ‘open4’ ### gem install open4

Open4.spawn ‘cat /dev/video’, :timeout=\>600, :stdout=\>buf=’’

p buf.size

-a
