* added IPC::Open3 examples from Benjamin Goldberg
Index: perlfaq8.pod =================================================================== RCS file: /cvs/public/perlfaq/perlfaq8.pod,v retrieving revision 1.9 diff -u -d -r1.9 perlfaq8.pod --- perlfaq8.pod 21 Jun 2002 04:33:43 -0000 1.9 +++ perlfaq8.pod 21 Jun 2002 04:48:43 -0000 @@ -620,6 +620,67 @@ script's STDOUT and STDERR, unless the system() command redirects them. Backticks and open() read B<only> the STDOUT of your command. +You can also use the open3() function from IPC::Open3. + +To capture a program's STDOUT, but discard it's STDERR: + + use IPC::Open3; + use File::Spec; + use Symbol qw(gensym); + open(NULL, ">", File::Spec->devnull); + my $pid = open3(gensym, \*PH, ">&NULL", "cmd"); + while( <PH> ) { } + waitpid($pid, 0); + +To capture a program's STDERR, but discard it's STDOUT: + + use IPC::Open3; + use File::Spec; + use Symbol qw(gensym); + open(NULL, ">", File::Spec->devnull); + my $pid = open3(gensym, ">&NULL", \*PH, "cmd"); + while( <PH> ) { } + waitpid($pid, 0); + +To capture a program's STDERR, and let it's STDOUT go to our own STDERR: + + use IPC::Open3; + use Symbol qw(gensym); + my $pid = open3(gensym, ">&STDERR", \*PH, "cmd"); + while( <PH> ) { } + waitpid($pid, 0); + +To read both a command's STDOUT and its STDERR separately, you can +redirect them to temp files, let the command run, then read the temp +files: + + use IPC::Open3; + use Symbol qw(gensym); + use IO::File; + local *CATCHOUT = IO::File->new_tempfile; + local *CATCHERR = IO::File->new_tempfile; + my $pid = open3(gensym, ">&CATCHOUT", ">&CATCHERR", "cmd"); + waitpid($pid, 0); + seek $_, 0, 0 for \*CATCHOUT, \*CATCHERR; + while( <CATCHOUT> ) {} + while( <CATCHERR> ) {} + +But there's no real need for *both* to be tempfiles... the following +should work just as well, without deadlocking: + + use IPC::Open3; + use Symbol qw(gensym); + use IO::File; + local *CATCHERR = IO::File->new_tempfile; + my $pid = open3(gensym, \*CATCHOUT, ">&CATCHERR", "cmd"); + while( <CATCHOUT> ) {} + waitpid($pid, 0); + seek CATCHERR, 0, 0; + while( <CATCHERR> ) {} + +And it'll be faster, too, since we can begin processing the program's +stdout immediately, rather than waiting for the program to finish. + With any of these, you can change file descriptors before the call: open(STDOUT, ">logfile");