# Capturing error msgs from output = \`cmd\`

**URL:** <https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252>\
**Category:** Ruby\
**Created:** [December 27, 2007, 3:54am UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252 "2007-12-27T03:54:05Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 3:54am UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/1 "2007-12-27T03:54:05Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 4:04am UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/2 "2007-12-27T04:04:36Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 5:31am UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/3 "2007-12-27T05:31:10Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 6:05am UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/4 "2007-12-27T06:05:05Z")

</div>

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](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

---

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 3:45pm UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/5 "2007-12-27T15:45:34Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 6:06am UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/6 "2007-12-27T06:06:50Z")

</div>

just saw that i duplicated a response. sorry.

---

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 3:54pm UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/7 "2007-12-27T15:54:25Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ribes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f4b2a3/32.png) [@ribes](https://www.ruby-forum.com/u/ribes)\
**Post date:** [December 27, 2007, 4:58pm UTC](https://www.ruby-forum.com/t/capturing-error-msgs-from-output-cmd/124252/8 "2007-12-27T16:58:30Z")

</div>

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
