Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Pipe, STDERR, STDOUT, and friends

by devnul (Monk)
on Sep 21, 2008 at 19:45 UTC ( #712873=perlquestion: print w/ replies, xml ) Need Help??
devnul has asked for the wisdom of the Perl Monks concerning the following question:


I'm really at a loss on the best way to approach this silly problem. I have a command-line program that does not properly generate exit codes (the source code for which is unavailable, so it can't be fixed).

Over the years, I've grown accustomed to using this nomenclature when executing an external command:
open(PIPE, '-|', $somecommand, $arg1, $arg2, ..., $arg(N), $filanem);
(where $filename is usually something grabbed from readdir, so it may contain spaces, etc)..

Unfortunately, the piece of data I need to grab to see if the command has failed is being sent to STDERR, not STDOUT.

For the life of me, I cannot seem to find a way to get the 3+argument version of open to give me what is going to STDOUT.

Alternatively, I am happy to go back to the 2-argument version, but how can I ensure that the filename I am passing in gets through the shell ok?...

...I've been up all night, so I apologize if this seems silly...

- dEvNuL

Comment on Pipe, STDERR, STDOUT, and friends
Download Code
Re: Pipe, STDERR, STDOUT, and friends
by moritz (Cardinal) on Sep 21, 2008 at 20:26 UTC
Re: Pipe, STDERR, STDOUT, and friends
by Anonymous Monk on Sep 21, 2008 at 20:29 UTC
Re: Pipe, STDERR, STDOUT, and friends
by ikegami (Pope) on Sep 21, 2008 at 21:00 UTC

    The question is, however, how to use open3 in this case. You could supply different handles for the child's STDOUT and STDERR, but then it becomes very hard to communicate with the child. (You'd need to use IO::Select to avoid deadlocks.)

    If you don't mind combining the child's STDOUT and STDERR into one stream, that's a much simpler option.

    $pid = open3( my $to_child, # Autovivified when false. my $fr_child, # Autovivified when false. undef, # Same as $fr_child when false. $somecommand, @args ); ... waitpid($pid, 0);
Re: Pipe, STDERR, STDOUT, and friends
by repellent (Priest) on Sep 22, 2008 at 03:22 UTC
    You can try redirecting STDERR to a file and then reading back from that file, for the duration of $somecommand. Perhaps something like:
    use Fcntl qw(:seek); # save STDERR filehandle open(my $ORIGSTDERR, ">&", STDERR); # create temporary filehandle to catch STDERR open(my $CATCHERR, "+>", undef) or die("cannot open temp file :: $!"); open(STDERR, ">&", $CATCHERR); # redirection ## STDERR is captured here ## open(PIPE, '-|', $somecommand, $arg1, $arg2, $argN, $filename); ... # restore STDERR filehandle open(STDERR, ">&", $ORIGSTDERR); # read captured STDERR from temporary filehandle seek($CATCHERR, 0, SEEK_SET); print "From CATCHERR: $_" while <$CATCHERR>; close($CATCHERR);

    Using a module I wrote (Pipe processes and Perl subroutines together), the STDERR capture can be further localized for the child process only:

Re: Pipe, STDERR, STDOUT, and friends
by gloryhack (Deacon) on Sep 22, 2008 at 08:04 UTC
    See IPC::Run. The documentation kinda sucks, but once you get your head around it you might find yourself reaching for it quite often. I do, anyway.
Re: Pipe, STDERR, STDOUT, and friends
by xdg (Monsignor) on Sep 22, 2008 at 12:36 UTC

    There are lots of CPAN modules to make this easier. If it's just a command you're running and you don't need to manage its STDIN, I'd use IO::CaptureOutput, which is my favorite swiss-army tool for capturing output either from Perl or from an external command. (So much my favorite that I took over maintainership when I needed bugs fixed and the author was non-responsive.)

    use IO::CaptureOutput qw( qxx ); my ($stdout, $stderr) = qxx( $somecommand, @args, $filename );


    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://712873]
Approved by Hue-Bond
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2014-07-31 03:49 GMT
Find Nodes?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:

    Results (244 votes), past polls