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?
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.
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:
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:
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”
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.
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
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.