How to separate stdout & stderr from executed shell command

J

jqwoods

I would like to create a method which executes a given shell command
and returns an array containing three things: 1) stdout of the command
as a string, 2) stderr of the command as a string, and 3) the exit
status. I'm having trouble figuring out how to get stdout and stderr
as separate output.

Here's an illustration of the desired result I'm after:

irb> my_exec_command("ls existant_file")
=> ["existant_file\n", "", 0]

irb> my_exec_command("ls NON_existant_file")
=> ["", "ls: NON_existant_file: No such file or directory\n", 2]

Any pointers on how to implement my_exec_command?
 
J

jqwoods

I would like to create a method which executes a given shell command
and returns an array containing three things: 1) stdout of the command
as a string, 2) stderr of the command as a string, and 3) the exit
status. I'm having trouble figuring out how to get stdout and stderr
as separate output.

Here's an illustration of the desired result I'm after:

irb> my_exec_command("ls existant_file")
=> ["existant_file\n", "", 0]

irb> my_exec_command("ls NON_existant_file")
=> ["", "ls: NON_existant_file: No such file or directory\n", 2]

Any pointers on how to implement my_exec_command?

PS: Unless there's a simpler way, if someone could just point me to an
API that provides stdout and stderr of sub-processes as IO objects, I
could probably figure it out from there. Thanks!
 
R

Rodrigo Bermejo

unknown said:
irb> my_exec_command("ls NON_existant_file")
=> ["", "ls: NON_existant_file: No such file or directory\n", 2]

Any pointers on how to implement my_exec_command?

PS: Unless there's a simpler way, if someone could just point me to an
API that provides stdout and stderr of sub-processes as IO objects, I
could probably figure it out from there. Thanks!

Take a look at the IO class.
The Pickaxe book has some good examples.

-r.
 
J

jqwoods

unknown said:
On Mar 14, 11:40 am, (e-mail address removed) wrote:
irb> my_exec_command("ls NON_existant_file")
=> ["", "ls: NON_existant_file: No such file or directory\n", 2]
Any pointers on how to implement my_exec_command?
PS: Unless there's a simpler way, if someone could just point me to an
API that provides stdout and stderr of sub-processes as IO objects, I
could probably figure it out from there. Thanks!

Take a look at the IO class.
The Pickaxe book has some good examples.

-r.

The closest API I could find is IO::popen. But as the doc for
IO::popen says "...the subprocess's standard input and output will be
connected..." So far I haven't found any way to get stdout and stderr
of a sub-process *separately*.

Any other pointers?
 
J

James Gray

unknown said:
On Mar 14, 11:40 am, (e-mail address removed) wrote:
irb> my_exec_command("ls NON_existant_file")
=> ["", "ls: NON_existant_file: No such file or directory\n", 2]
Any pointers on how to implement my_exec_command?
PS: Unless there's a simpler way, if someone could just point me
to an
API that provides stdout and stderr of sub-processes as IO
objects, I
could probably figure it out from there. Thanks!

Take a look at the IO class.
The Pickaxe book has some good examples.

-r.

The closest API I could find is IO::popen. But as the doc for
IO::popen says "...the subprocess's standard input and output will be
connected..." So far I haven't found any way to get stdout and stderr
of a sub-process *separately*.

Any other pointers?

Yes, Ruby comes with a standard library for this, called open3. Here
are the docs for the method you want:

$ qri Open3#popen3
----------------------------------------------------------- Open3#popen3
popen3(*cmd) {|| ...}
------------------------------------------------------------------------
Open stdin, stdout, and stderr streams and start external
executable. Non-block form:

require 'open3'

[stdin, stdout, stderr] = Open3.popen3(cmd)

Block form:

require 'open3'

Open3.popen3(cmd) { |stdin, stdout, stderr| ... }

The parameter cmd is passed directly to Kernel#exec.

Hope that helps.

James Edward Gray II
 
J

jqwoods

unknown wrote:
On Mar 14, 11:40 am, (e-mail address removed) wrote:
irb> my_exec_command("ls NON_existant_file")
=> ["", "ls: NON_existant_file: No such file or directory\n", 2]
Any pointers on how to implement my_exec_command?
PS: Unless there's a simpler way, if someone could just point me
to an
API that provides stdout and stderr of sub-processes as IO
objects, I
could probably figure it out from there. Thanks!
Take a look at the IO class.
The Pickaxe book has some good examples.
-r.
The closest API I could find is IO::popen. But as the doc for
IO::popen says "...the subprocess's standard input and output will be
connected..." So far I haven't found any way to get stdout and stderr
of a sub-process *separately*.
Any other pointers?

Yes, Ruby comes with a standard library for this, called open3. Here
are the docs for the method you want:

$ qri Open3#popen3
----------------------------------------------------------- Open3#popen3
popen3(*cmd) {|| ...}
------------------------------------------------------------------------
Open stdin, stdout, and stderr streams and start external
executable. Non-block form:

require 'open3'

[stdin, stdout, stderr] = Open3.popen3(cmd)

Block form:

require 'open3'

Open3.popen3(cmd) { |stdin, stdout, stderr| ... }

The parameter cmd is passed directly to Kernel#exec.

Hope that helps.

James Edward Gray II

Exactly what I was looking for. Thanks!
 
A

Arlen Cuss

[Note: parts of this message were removed to make it a legal post.]

Hi,

require "open3"

stdin, stdout, stderr = Open3.popen3('nroff -man')

Try it!

Arlen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top