Capturing error msgs from output = `cmd`


V

Victor Reyes

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

Hello Team,

I wrote the simple piece of code below which under "normal" circumstances it
works fine.
If, however, the command executed generates an error msg, the error is
displayed on the screen.
This is a behaviour which I don't want.
I would like to capture ALL output generated by the command and return it to
the caller.
I tried different tricks but nothing worked. The question is:

How can I capture ALL output from line: *userCMD_output = `#{input}`*
including stderr???

require 'socket'
port = 19557
server = TCPServer.new("", port)

while (session = server.accept)
input = session.gets
userCMD_output = `#{input}`
session.write("#{userCMD_output}")
session.close
end

while you are at it, is there any way to obtain the caller's hostname or IP
address?

Thank you

Victor
 
Ad

Advertisements

T

Tim Hunter

Victor said:
Hello Team,

I wrote the simple piece of code below which under "normal" circumstances it
works fine.
If, however, the command executed generates an error msg, the error is
displayed on the screen.
This is a behaviour which I don't want.
I would like to capture ALL output generated by the command and return it to
the caller.
I tried different tricks but nothing worked. The question is:

How can I capture ALL output from line: *userCMD_output = `#{input}`*
including stderr???

When you use backticks to capture the output from a command, what you
get is whatever the command writes to stdout. If the command writes an
error message to stderr you can't capture it.

Check out the open3 library and the popen3 method instead.

$ ri 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.
 
J

James Gray

When you use backticks to capture the output from a command, what
you get is whatever the command writes to stdout. If the command
writes an error message to stderr you can't capture it.

Well, you could fold STDERR into STDOUT. In my Unix shell that's done
with:

`#{cmd} 2>&1`

Hope that helps.

James Edward Gray II
 
T

Tom Metge

Well, you could fold STDERR into STDOUT. In my Unix shell that's
done with:

`#{cmd} 2>&1`

Hope that helps.

James Edward Gray II

that's a great idea. alternately, you could use open3:

http://ruby-doc.org/stdlib/libdoc/open3/rdoc/index.html

it does make it a bit easier to do error checking/handling (by
differentiating stderr from stdout). you can use nil for the values
you don't want...

nil, stdout, stderr = popen3("cmd")

tom
 
T

Tom Metge

just saw that i duplicated a response. sorry.

Well, you could fold STDERR into STDOUT. In my Unix shell that's
done with:

`#{cmd} 2>&1`

Hope that helps.

James Edward Gray II
 
V

Victor Reyes

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

Team,

First, thank you for all your suggestions. They are greatly appreciated.

I tried the:
*userCMD_output* *= `#{input} 2>&1`*
But could not capture the error. Matter of facts the error to the *ls *command
was displayed on the screen as:
*ls: 0653-341 The file totot does not exist. *

Second, I tried using the *Open3* method and when I tried to display the
content of stdin, stdout and stderr just to inspect their contents, this is
what's there:

*stdin, stdout, stderr = Open3.popen3(input)*

puts stdin
puts stdout
puts stderr

*#<IO:0x20060638>
#<IO:0x200605fc>
#<IO:0x20060598> *

It looks like I can't get this thing to work.

Thanks a bunch for all the help from everyone.

Victor
 
Ad

Advertisements

S

Stefano Crocco

Alle gioved=EC 27 dicembre 2007, Victor Reyes ha scritto:
Team,

First, thank you for all your suggestions. They are greatly appreciated.

I tried the:
*userCMD_output* *=3D `#{input} 2>&1`*
But could not capture the error. Matter of facts the error to the *ls
*command was displayed on the screen as:
*ls: 0653-341 The file totot does not exist. *

Are you trying it in IRB? in this case, maybe what you see is the return=20
value. Try puts userCMD_output and see whether it contains the error messag=
e=20
or not. I tried this and it works:

irb(main):001:0> res =3D `ls abc 2>&1`
=3D> "ls: impossibile accedere a abc: No such file or directory\n"
irb(main):002:0> res
=3D> "ls: impossibile accedere a abc: No such file or directory\n"
Second, I tried using the *Open3* method and when I tried to display the
content of stdin, stdout and stderr just to inspect their contents, this = is
what's there:

*stdin, stdout, stderr =3D Open3.popen3(input)*

puts stdin
puts stdout
puts stderr

*#<IO:0x20060638>
#<IO:0x200605fc>
#<IO:0x20060598> *

I don't understand how this works very well (I just started experimenting w=
ith=20
Open3 yesterday), but I think you need to call their read methods, just as=
=20
you'd do with a file:

puts stdout.read
=3D> ...

This won't work with stdin (if I remember correctly) because it's not open =
for=20
writing.

I hope this helps

Stefano
 
Ad

Advertisements

V

Victor Reyes

Hi, Stefano,

Well I have partial success at last!

The expression *res =3D `ls abc 2>&1`* works fine on the irb. But not outsi=
de
of it.

For the *Open3* method I tried your suggestion using the *stderr.read* and
it works fine.
I just needed a way to return the outcome of the request to the client
caller.
Since *Open3* works I will stay with it.

Thanks to you, Tim Hunter, James Edward Gray II and Tom Metge for all your
help. It is really appreciated.
One day, when I become good at using Ruby, I might be able to help others.

Victor
 

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

Top