Capturing error msgs from output = `cmd`

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

Victor R. wrote:

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.

On Dec 26, 2007, at 9:03 PM, Tim H. wrote:

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.

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

#{cmd} 2>&1

Hope that helps.

James Edward G. II

On Dec 26, 2007, at 9:30 PM, James G. wrote:

This is a behaviour which I don’t want.
you get is whatever the command writes to stdout. If the command

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

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

just saw that i duplicated a response. sorry.

Alle giovedì 27 dicembre 2007, Victor R. ha scritto:

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. *

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

irb(main):001:0> res = ls abc 2>&1
=> “ls: impossibile accedere a abc: No such file or directory\n”
irb(main):002:0> res
=> “ls: impossibile accedere a abc: No such file or directory\n”

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

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

puts stdout.read
=> …

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

I hope this helps

Stefano

Hi, Stefano,

Well I have partial success at last!

The expression res = ls abc 2>&1 works fine on the irb. But not
outside
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 H., James Edward G. II and Tom M. 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