Capturing the Output and Error Streams from a Unix Shell Command






Capturing the Output and Error Streams from a Unix Shell Command

Problem

You want to run an external program as in Recipe 20.8, but you also want to capture the standard error stream. Using popen only gives you access to the standard output.

Solution

Use the open3 library in the Ruby standard library. Its popen3 method takes a code block, to which it passes three IO streams: one each for standard input, output, and error.

Suppose you perform the Unix ls command to list a nonexistent directory. ls will rightly object to this and write an error message to its standard error stream. If you invoked ls with IO.popen or the %x{} construction, that error message is passed right along to the standard error stream of your Ruby process. You can't capture it or suppress it:

	%x{ls no_such_directory}
	# ls: no_such_directory: No such file or directory

But if you use popen3, you can grab that error message and do whatever you want with it:

	require 'open3'

	Open3.popen3('ls -l no_such_directory') { |stdin, stdout, stderr| stderr.read }
	# => "ls: no_such_directory: No such file or directory\n"

Discussion

The same caveats in the previous recipe apply to the IO streams returned by popen3. If you're running a command that accepts data on standard input, and you read from stdout before closing stdin, your process will hang.

Unlike IO.popen, the popen3 method is only implemented on Unix systems. However, the win32-open3 package (part of the Win32Utils project) provides a popen3 implementation.

See Also



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows