"open" pipe with stderr 
Author Message
 "open" pipe with stderr

I just starting learning Perl this week, and so far things have been
quite smooth.  (The Camel book has been invaluable!)  There's one
thing I'm stuck on, tho.  I'd like to use "open" to open a pipe, but
I'd like to read both the stdout and the stderr from the pipe.
Doing open( FH, "command |" ) does a fine job of getting me the
stdout stream.  But I expected to be able to do open( FH, "command |&" )
to also get stderr, but the open is failing.  Any ideas?

ADVthanxANCE.

--

Texas Instruments, Inc.                 phone = (214) 997-2428
ASIC Software Engineering Services      MSGID = AMJ1



Wed, 04 Sep 1996 08:19:57 GMT  
 "open" pipe with stderr

:I just starting learning Perl this week, and so far things have been
:quite smooth.  (The Camel book has been invaluable!)  There's one
:thing I'm stuck on, tho.  I'd like to use "open" to open a pipe, but
:I'd like to read both the stdout and the stderr from the pipe.
:Doing open( FH, "command |" ) does a fine job of getting me the
:stdout stream.  But I expected to be able to do open( FH, "command |&" )
:to also get stderr, but the open is failing.  Any ideas?

|& is not standard shell syntax.  Perl always uses /bin/sh, not whatever
shell you should happen to be running.  This is a feature.

2.24) How can I capture STDERR from an external command?

    There are three basic ways of running external commands:

        system $cmd;
        $output = `$cmd`;
        open (PIPE, "cmd |");

    In the first case, both STDOUT and STDERR will go the same place as
    the script's versions of these, unless redirected.  You can always put
    them where you want them and then read them back when the system
    returns.  In the second and third cases, you are reading the STDOUT
    *only* of your command.  If you would like to have merged STDOUT and
    STDERR, you can use shell file-descriptor redirection to dup STDERR to
    STDOUT:

        $output = `$cmd 2>&1`;
        open (PIPE, "cmd 2>&1 |");

    Another possibility is to run STDERR into a file and read the file
    later, as in

        $output = `$cmd 2>some_file`;
        open (PIPE, "cmd 2>some_file |");

    Here's a way to read from both of them and know which descriptor
    you got each line from.  The trick is to pipe only STDERR through
    sed, which then marks each of its lines, and then sends that
    back into a merged STDOUT/STDERR stream, from which your Perl program
    then reads a line at a time:

        open (CMD,
          "3>&1 (cmd args 2>&1 1>&3 3>&- | sed 's/^/STDERR:/' 3>&-) 3>&- |");

        while (<CMD>) {
          if (s/^STDERR://)  {
              print "line from stderr: ", $_;
          } else {
              print "line from stdout: ", $_;
          }
        }

    Be apprised that you *must* use Bourne shell redirection syntax
    here, not csh!  In fact, you can't even do these things with csh.
    For details on how lucky you are that perl's system() and backtick
    and pipe opens all use Bourne shell, fetch the file from convex.com
    called /pub/csh.whynot -- and you'll be glad that perl's shell
    interface is the Bourne shell.

    There's an &open3 routine out there which will be merged with
    &open2 in perl5 production.

Note that it's probably much easier to do this:

        open (CMD, "cmd args | sed 's/^/STDOUT:/' |");

        while (<CMD>) {
          if (s/^STDOUT://)  {
              print "line from stdout: ", $_;
          } else {
              print "line from stderr: ", $_;
          }
        }

But much less effective in terms of job security. :-)

--tom
--

      "Will Hack Perl for Fine Food and Fun"
        Boulder Colorado  303-444-3212



Thu, 05 Sep 1996 01:08:04 GMT  
 "open" pipe with stderr

Quote:

>I just starting learning Perl this week, and so far things have been
>quite smooth.  (The Camel book has been invaluable!)  There's one
>thing I'm stuck on, tho.  I'd like to use "open" to open a pipe, but
>I'd like to read both the stdout and the stderr from the pipe.
>Doing open( FH, "command |" ) does a fine job of getting me the
>stdout stream.  But I expected to be able to do open( FH, "command |&" )
>to also get stderr, but the open is failing.  Any ideas?

>ADVthanxANCE.

>--

>Texas Instruments, Inc.                 phone = (214) 997-2428
>ASIC Software Engineering Services      MSGID = AMJ1

To date there are two ways of doing what you want. 1) forking out the process
and using popen and dup2 or... 2) using open3.pl (distributed with perl5). My
vote is to use open3.pl if you are new to perl or do not have much experience
forking out your own processes. You see all open() is doing is creating a pipe
, spawning out your process, duping the stdout from your process to the pipe,
reading the info, and making sure your process exits cleanly. Good luck.

        -dave :-)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dave Rensin                     College Of Engineering


                        ^
                       ()  
                      \__/
                      -<>-
                       /\

(will hack Perl code in spite of what my boss might say)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



Fri, 06 Sep 1996 21:45:50 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. open("...|") and stderr

2. Piping in stderr when creating a pipe with the open call

3. "character class ""bug""

4. Problem with an unexpected "broken pipe"

5. IO::Socket "Broken pipe" crashes script

6. "Access denied" with Win32::Pipe

7. "Broken pipe"

8. Closing pipes results in "uninitialized value"

9. Troubles "perl"ifying a shellscript that uses pipes

10. Help reading pipes "unbuffered"?

11. "pipe" code - mail- e-mail

12. open a piped command including stderr

 

 
Powered by phpBB® Forum Software