n ot how to capture output in perl · how to capture output in perl david golden [email protected]...

83
Copyright © 2006 David A. Golden How to capture output in Perl David Golden [email protected] Spring 2009 NOT

Upload: phungdieu

Post on 06-Apr-2018

240 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

Copyright © 2006 David A. Golden

How to capture output in Perl

David [email protected]

Spring 2009

NOT

Page 2: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

1 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

Page 3: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

2 Copyright © 2009 David A. Golden

Simplequestion

Page 4: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

3 Copyright © 2009 David A. Golden

Deceptivelysimple

Page 5: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

4 Copyright © 2009 David A. Golden

So what's easy?

Page 6: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

5 Copyright © 2009 David A. Golden

STDOUTof a command

Page 7: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

6 Copyright © 2009 David A. Golden

Backticks

$out = `perl –E 'say "Hello World"'`;

Page 8: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

7 Copyright © 2009 David A. Golden

In real life,use $^X not perl

$out = `$^X –E 'say "Hello World"'`;$out = `perl –E 'say "Hello World"'`;

Digression…

Page 9: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

8 Copyright © 2009 David A. Golden

$^X = current perl'perl' = first in PATH

$out = `$^X –E 'say "Hello World"'`;$out = `perl –E 'say "Hello World"'`;

Digression…

Page 10: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

9 Copyright © 2009 David A. Golden

piped open()

open PIPE, qq{perl -E 'say "Hello World"' |};$out = do { local $/; <PIPE> };

Page 11: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

10 Copyright © 2009 David A. Golden

Backticks and open use the shell

Page 12: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

11 Copyright © 2009 David A. Golden

Different shellsDifferent quotes

Page 13: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

12 Copyright © 2009 David A. Golden

/bin/shvs.

cmd.exe$out = `perl –E 'say "Hello World"'`;$out = `perl –E "say qq{Hello World}"`;

Page 14: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

13 Copyright © 2009 David A. Golden

Filenames can contain spaces

$file = "Hello World.txt";$out = `perl –E 'say shift' $file`;

Page 15: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

14 Copyright © 2009 David A. Golden

How the shell sees it

$ perl –E 'say shift' Hello World.txtHello

Page 16: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

15 Copyright © 2009 David A. Golden

Need backticks like system(@cmd)

Page 17: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

16 Copyright © 2009 David A. Golden

IPC::System::Simple

use IPC::System::Simple 'capture';@cmd = ('perl', '-E', 'say shift', 'Hello World.txt');$out = capture(@cmd);

Page 18: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

17 Copyright © 2009 David A. Golden

CapturingSTDERR?

Page 19: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

18 Copyright © 2009 David A. Golden

perlfaq –q capture

Page 20: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

19 Copyright © 2009 David A. Golden

How can I capture STDERR from an external command?There are three basic ways of running external commands:

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

With system(), both STDOUT and STDERR will go the same place as the script’sSTDOUT and STDERR, unless the system() command redirects them. Backticks andopen() read only the STDOUT of your command.

You can also use the open3() function from IPC::Open3. Benjamin Goldbergprovides some sample code:

To capture a program’s STDOUT, but discard its 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 its 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 its 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 redirectthem 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_tmpfile;local *CATCHERR = IO::File->new_tmpfile;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 shouldwork just as well, without deadlocking:

use IPC::Open3;use Symbol qw(gensym);use IO::File;local *CATCHERR = IO::File->new_tmpfile;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 stdoutimmediately, rather than waiting for the program to finish.

With any of these, you can change file descriptors before the call:

open(STDOUT, ">logfile");system("ls");

or you can use Bourne shell file-descriptor redirection:

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

You can also use file-descriptor redirection to make STDERR a duplicate ofSTDOUT:

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

Note that you cannot simply open STDERR to be a dup of STDOUT in your Perlprogram and avoid calling the shell to do the redirection. This doesn’t work:

open(STDERR, ">&STDOUT");$alloutput = `cmd args`; # stderr still escapes

This fails because the open() makes STDERR go to where STDOUT was going at thetime of the open(). The backticks then make STDOUT go to a string, but don’tchange STDERR (which still goes to the old STDOUT).

Note that you must use Bourne shell (sh(1)) redirection syntax in backticks,not csh(1)! Details on why Perl’s system() and backtick and pipe opens all usethe Bourne shell are in the versus/csh.whynot article in the "Far More Than YouEver Wanted To Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgzTo capture a command’s STDERR and STDOUT together:

$output = `cmd 2>&1`; # either with backticks$pid = open(PH, "cmd 2>&1 |"); # or with an open pipewhile (<PH>) { } # plus a read

To capture a command’s STDOUT but discard its STDERR:

$output = `cmd 2>/dev/null`; # either with backticks$pid = open(PH, "cmd 2>/dev/null |"); # or with an open pipewhile (<PH>) { } # plus a read

To capture a command’s STDERR but discard its STDOUT:

$output = `cmd 2>&1 1>/dev/null`; # either with backticks$pid = open(PH, "cmd 2>&1 1>/dev/null |"); # or with an open pipewhile (<PH>) { } # plus a read

To exchange a command’s STDOUT and STDERR in order to capture the STDERR butleave its STDOUT to come out our old STDERR:

$output = `cmd 3>&1 1>&2 2>&3 3>&-`; # either with backticks$pid = open(PH, "cmd 3>&1 1>&2 2>&3 3>&-|");# or with an open pipewhile (<PH>) { } # plus a read

To read both a command’s STDOUT and its STDERR separately, it’s easiest toredirect them separately to files, and then read from those files when theprogram is done:

system("program args 1>program.stdout 2>program.stderr");

Ordering is important in all these examples. That’s because the shellprocesses file descriptor redirections in strictly left to right order.

system("prog args 1>tmpfile 2>&1");system("prog args 2>&1 1>tmpfile");

The first command sends both standard out and standard error to the temporaryfile. The second command sends only the old standard output there, and the oldstandard error shows up on the old standard out.

Page 21: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

20 Copyright © 2009 David A. Golden

Screw all that!*

* Actually, it's good reading on the fundamentals if you want to reinvent the wheel

Page 22: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

21 Copyright © 2009 David A. Golden

CPAN, help!

Page 23: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

22 Copyright © 2009 David A. Golden

IPC::Run3

use IPC::Run3 'run3';run3(\@cmd, undef, \$out, \$err);

Page 24: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

23 Copyright © 2009 David A. Golden

Variations

use IPC::Run3 'run3';run3(\@cmd, \&input, \$out, \@err);

Page 25: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

24 Copyright © 2009 David A. Golden

Capturing STDOUT& STDERR together?

Page 26: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

25 Copyright © 2009 David A. Golden

Sure!

use IPC::Run3 'run3';run3(\@cmd, undef, \$both, \$both);

Page 27: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

26 Copyright © 2009 David A. Golden

What's the catch?

Page 28: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

27 Copyright © 2009 David A. Golden

User interaction

Page 29: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

28 Copyright © 2009 David A. Golden

prompt.pl#!/usr/bin/perl

while( 1 ) {print "Type 'exit' to quit:\n"$line = <STDIN>;last if $line =~ /^exit$/;print "You said: $_";

}

Page 30: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

29 Copyright © 2009 David A. Golden

Prompts are captured

# try-run3.pluse IPC::Run3 'run3';print "Running prompt.pl\n";run3('perl prompt.pl', undef, \$out, \$err);

Page 31: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

30 Copyright © 2009 David A. Golden

Hangs$ perl try-run3.plRunning prompt.pl

( … nothing else happens … eventually hit CTRL-C … )

Page 32: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

31 Copyright © 2009 David A. Golden

Need to captureand echo to screen

Page 33: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

32 Copyright © 2009 David A. Golden

Tee?

system( "$cmd | tee output.log" );$out = do {

local (@ARGV,$/) = "output.log"; <>};

Page 34: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

33 Copyright © 2009 David A. Golden

If 'tee' exists*

* Tee.pm provides 'ptee'

Page 35: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

34 Copyright © 2009 David A. Golden

Gives wrong exit value

system( "$cmd | tee output.log" );if ($? == 0) { print "tee ran ok" };

Page 36: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

35 Copyright © 2009 David A. Golden

IPC::Open3

use IPC::Open3;my $pid = open3(\*CHILD_IN, \*CHILD_OUT, \*CHILD_ERR, @cmd

);

Page 37: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

36 Copyright © 2009 David A. Golden

select() between output handles# Adapted and simplified from IPC::Open3::Simpleuse IPC::Open3;use IO::Select;my ($out, $err) = ( '', '' );my $pid =

open3(\*CHILD_IN, \*CHILD_OUT, \*CHILD_ERR, @cmd);my $reader = IO::Select->new(\*CHILD_OUT, \*CHILD_ERR);while ( my @ready = $reader->can_read() ) {

foreach my $fh (@ready) {my $line = <$fh>;if (!defined $line) { $reader->remove($fh);$fh->close();

} else {if (fileno($fh) == fileno(\*CHILD_OUT)) {$out .= $line;print STDOUT $line;

} elsif (fileno($fh) == fileno(\*CHILD_ERR)) {$err .= $lineprint STDERR $line;

}}

}}waitpid($pid, 0);

Page 38: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

37 Copyright © 2009 David A. Golden

But no select() on handles for Win32

Page 39: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

38 Copyright © 2009 David A. Golden

IPC::Run

Page 40: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

39 Copyright © 2009 David A. Golden

Win32 supportis 'experimental'

Page 41: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

40 Copyright © 2009 David A. Golden

select() on sockets instead of filehandles

Page 42: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

41 Copyright © 2009 David A. Golden

Still have to writeinteractivity code

yourself

Page 43: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

42 Copyright © 2009 David A. Golden

Does anything just DWIW?

Page 44: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

43 Copyright © 2009 David A. Golden

IPC::Cmd

use IPC::Cmd 'run';my ( $success, $error_code,

$full_buf, $stdout_buf, $stderr_buf) = run( command => $cmd, verbose => 1 );

Page 45: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

44 Copyright © 2009 David A. Golden

In Perl corein 5.10

Page 46: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

45 Copyright © 2009 David A. Golden

Uses IPC::Runor IPC::Open3

Page 47: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

46 Copyright © 2009 David A. Golden

Interactiveplus capture

Page 48: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

47 Copyright © 2009 David A. Golden

Or maybe notif ( IPC::Cmd->can_capture_buffer ) {

@results = run(@stuff);}else {

die "Now what?!";}

Page 49: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

48 Copyright © 2009 David A. Golden

Capturing Perl?

Page 50: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

49 Copyright © 2009 David A. Golden

Tied filehandles

tie *STDOUT, $class;print "This string captured by $class";

Page 51: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

50 Copyright © 2009 David A. Golden

IO::CaptureIO::Tee

Filter::HandleTest::OutputTie::STDOUTTie::STDERR

Page 52: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

51 Copyright © 2009 David A. Golden

XS (or C) fails

use Inline C => <<'END_C';void greet() { printf( "Tie won't capture this\n" ); }END_C

greet;

Page 53: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

52 Copyright © 2009 David A. Golden

system() fails

use Test::Output;stdout_is { system "echo 'Hello World'" }"Hello World\n", "Got Hello World"; # Not OK

Page 54: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

53 Copyright © 2009 David A. Golden

IO::CaptureOutput

use IO::CaptureOutput 'capture';capture { print "Hello World\n"

} => \$out, \$err;

Page 55: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

54 Copyright © 2009 David A. Golden

Perl, XS or system()

use IO::CaptureOutput 'capture';capture { system "echo 'Hello World'"

} => \$out, \$err;

Page 56: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

55 Copyright © 2009 David A. Golden

STDOUT & STDERR

use IO::CaptureOutput 'capture';capture { system "echo 'Hello World'"

} => \$both, \$both;

Page 57: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

56 Copyright © 2009 David A. Golden

Portable, too

Page 58: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

57 Copyright © 2009 David A. Golden

Interactive?

Page 59: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

58 Copyright © 2009 David A. Golden

No

use IO::CaptureOutput 'capture';capture { system "perl prompt.pl" # hangs

} => \$both, \$both;

Page 60: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

59 Copyright © 2009 David A. Golden

File::Teeuse File::Tee 'tee);'tee(STDOUT, '>', 'stdout.txt');print "Hello World\n";system "perl prompt.pl";# read back stdout.txt on your own

Page 61: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

60 Copyright © 2009 David A. Golden

But uses piped open

Page 62: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

61 Copyright © 2009 David A. Golden

Not portable

Excerpt from 'perldoc perlport':

open to "|-" and "-|" are unsupported. (Mac OS, Win32, RISC OS)

Page 63: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

62 Copyright © 2009 David A. Golden

Now what?

Page 64: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

63 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

Page 65: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

64 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

… from STDOUT, STDERR or both

Page 66: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

65 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

… from STDOUT, STDERR or both… from Perl, XS or a command

Page 67: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

66 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

… from STDOUT, STDERR or both… from Perl, XS or a command… interactive with the terminal

Page 68: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

67 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

… from STDOUT, STDERR or both… from Perl, XS or a command… interactive with the terminal… that is reasonably portable

Page 69: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

68 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

… from STDOUT, STDERR or both… from Perl, XS or a command… interactive with the terminal… that is reasonably portable… with a single module

Page 70: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

69 Copyright © 2009 David A. Golden

Didn't exist

Page 71: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

70 Copyright © 2009 David A. Golden

So I wrote it

Page 72: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

71 Copyright © 2009 David A. Golden

Capture::Tinyuse Capture::Tiny 'capture';$out = capture {print "Hello World\n";

};

Page 73: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

72 Copyright © 2009 David A. Golden

STDOUT & STDERRuse Capture::Tiny 'capture';($out, $err) = capture {print "Hello World\n";print STDERR "Goodbye World\n";

};

Page 74: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

73 Copyright © 2009 David A. Golden

Bothuse Capture::Tiny 'capture_merged';$both = capture_merged {print "Hello World\n";print STDERR "Goodbye World\n";

};

Page 75: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

74 Copyright © 2009 David A. Golden

XS or commanduse Capture::Tiny 'capture';($out, $err) = capture {system "echo 'Hello World'";

};

Page 76: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

75 Copyright © 2009 David A. Golden

Interactiveuse Capture::Tiny 'tee';($out, $err) = tee {system "perl prompt.pl";

};

Page 77: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

76 Copyright © 2009 David A. Golden

Fairly portable

Does need 'fork' except on Win32/OS2

Page 78: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

77 Copyright © 2009 David A. Golden

Functional, not OO or start/stop/gather

@results = map { scalar capture { system "$cmd $_" } } @args;

Page 79: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

78 Copyright © 2009 David A. Golden

Small

SLOCIPC::Run 3,522 IPC::Run3 654 IPC::Cmd 421IPC::Open3 187File::Tee 215IO::CaptureOutput 181Capture::Tiny 163

Page 80: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

79 Copyright © 2009 David A. Golden

A single tool that works

Page 81: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

80 Copyright © 2009 David A. Golden

"How do I capture output in Perl?"

Page 82: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

81 Copyright © 2009 David A. Golden

use Capture::Tiny

Page 83: N OT How to capture output in Perl · How to capture output in Perl David Golden dagolden@cpan.org Spring 2009 N OT. ... Note that you cannot simply open STDERR to be a dup of STDOUT

82 Copyright © 2009 David A. Golden

Questions?