1 # Copyright (c) 2009 by David Golden. All rights reserved.
2 # Licensed under Apache License, Version 2.0 (the "License").
3 # You may not use this file except in compliance with the License.
4 # A copy of the License was distributed with this file or you may obtain a
5 # copy of the License from http://www.apache.org/licenses/LICENSE-2.0
15 use File::Temp qw/tempfile tmpnam/;
16 # Get PerlIO or fake it
17 BEGIN { eval { require PerlIO; 1 } or *PerlIO::get_layers = sub { return () }; }
19 our $VERSION = '0.06';
20 $VERSION = eval $VERSION; ## no critic
21 our @ISA = qw/Exporter/;
22 our @EXPORT_OK = qw/capture capture_merged tee tee_merged/;
23 our %EXPORT_TAGS = ( 'all' => \@EXPORT_OK );
25 my $IS_WIN32 = $^O eq 'MSWin32';
27 our $DEBUG = $ENV{PERL_CAPTURE_TINY_DEBUG};
29 open $DEBUGFH, ">&STDERR" if $DEBUG;
31 *_debug = $DEBUG ? sub(@) { print {$DEBUGFH} @_ } : sub(){0};
33 #--------------------------------------------------------------------------#
34 # command to tee output -- the argument is a filename that must
35 # be opened to signal that the process is ready to receive input.
36 # This is annoying, but seems to be the best that can be done
37 # as a simple, portable IPC technique
38 #--------------------------------------------------------------------------#
39 my @cmd = ($^X, '-e', '$SIG{HUP}=sub{exit}; '
40 . 'if( my $fn=shift ){ open my $fh, qq{>$fn}; print {$fh} $$; close $fh;} '
41 . 'my $buf; while (sysread(STDIN, $buf, 2048)) { '
42 . 'syswrite(STDOUT, $buf); syswrite(STDERR, $buf)}'
45 #--------------------------------------------------------------------------#
46 # filehandle manipulation
47 #--------------------------------------------------------------------------#
50 my ($fh, $layers) = @_;
51 _debug("# requested layers (@{$layers}) to $fh\n");
53 my @unique = grep { $_ ne 'unix' and $_ ne 'perlio' and !$seen{$_}++ } @$layers;
54 _debug("# applying unique layers (@unique) to $fh\n");
55 binmode($fh, join(":", "", "raw", @unique));
60 no strict 'refs'; ## no critic
61 return *{$glob}{NAME};
65 open $_[0], $_[1] or Carp::confess "Error from open(" . join(q{, }, @_) . "): $!";
66 _debug( "# open " . join( ", " , map { defined $_ ? _name($_) : 'undef' } @_ ) . " as " . fileno( $_[0] ) . "\n" );
70 close $_[0] or Carp::confess "Error from close(" . join(q{, }, @_) . "): $!";
71 _debug( "# closed " . ( defined $_[0] ? _name($_[0]) : 'undef' ) . "\n" );
74 my %dup; # cache this so STDIN stays fd0
78 if ( ! defined fileno STDIN ) {
79 $proxy_count{stdin}++;
80 if (defined $dup{stdin}) {
81 _open \*STDIN, "<&=" . fileno($dup{stdin});
82 _debug( "# restored proxy STDIN as " . (defined fileno STDIN ? fileno STDIN : 'undef' ) . "\n" );
85 _open \*STDIN, "<" . File::Spec->devnull;
86 _debug( "# proxied STDIN as " . (defined fileno STDIN ? fileno STDIN : 'undef' ) . "\n" );
87 _open $dup{stdin} = IO::Handle->new, "<&=STDIN";
89 $proxies{stdin} = \*STDIN;
90 binmode(STDIN, ':utf8') if $] >= 5.008;
92 if ( ! defined fileno STDOUT ) {
93 $proxy_count{stdout}++;
94 if (defined $dup{stdout}) {
95 _open \*STDOUT, ">&=" . fileno($dup{stdout});
96 _debug( "# restored proxy STDOUT as " . (defined fileno STDOUT ? fileno STDOUT : 'undef' ) . "\n" );
99 _open \*STDOUT, ">" . File::Spec->devnull;
100 _debug( "# proxied STDOUT as " . (defined fileno STDOUT ? fileno STDOUT : 'undef' ) . "\n" );
101 _open $dup{stdout} = IO::Handle->new, ">&=STDOUT";
103 $proxies{stdout} = \*STDOUT;
104 binmode(STDOUT, ':utf8') if $] >= 5.008;
106 if ( ! defined fileno STDERR ) {
107 $proxy_count{stderr}++;
108 if (defined $dup{stderr}) {
109 _open \*STDERR, ">&=" . fileno($dup{stderr});
110 _debug( "# restored proxy STDERR as " . (defined fileno STDERR ? fileno STDERR : 'undef' ) . "\n" );
113 _open \*STDERR, ">" . File::Spec->devnull;
114 _debug( "# proxied STDERR as " . (defined fileno STDERR ? fileno STDERR : 'undef' ) . "\n" );
115 _open $dup{stderr} = IO::Handle->new, ">&=STDERR";
117 $proxies{stderr} = \*STDERR;
118 binmode(STDERR, ':utf8') if $] >= 5.008;
125 _debug( "# unproxing " . join(" ", keys %proxies) . "\n" );
126 for my $p ( keys %proxies ) {
128 _debug( "# unproxied " . uc($p) . " ($proxy_count{$p} left)\n" );
129 if ( ! $proxy_count{$p} ) {
131 _close $dup{$p} unless $] < 5.008; # 5.6 will have already closed this as dup
138 my %handles = map { $_, IO::Handle->new } qw/stdin stdout stderr/;
139 _debug( "# copying std handles ...\n" );
140 _open $handles{stdin}, "<&STDIN";
141 _open $handles{stdout}, ">&STDOUT";
142 _open $handles{stderr}, ">&STDERR";
148 _open \*STDIN, "<&" . fileno $handles->{stdin};
149 _open \*STDOUT, ">&" . fileno $handles->{stdout};
150 _open \*STDERR, ">&" . fileno $handles->{stderr};
153 #--------------------------------------------------------------------------#
155 #--------------------------------------------------------------------------#
158 my ($which, $stash) = @_;
160 $stash->{$_}{$which} = IO::Handle->new for qw/tee reader/;
161 pipe $stash->{reader}{$which}, $stash->{tee}{$which};
162 _debug( "# pipe for $which\: " . _name($stash->{tee}{$which}) . " "
163 . fileno( $stash->{tee}{$which} ) . " => " . _name($stash->{reader}{$which})
164 . " " . fileno( $stash->{reader}{$which}) . "\n" );
165 select((select($stash->{tee}{$which}), $|=1)[0]); # autoflush
166 # setup desired redirection for parent and child
167 $stash->{new}{$which} = $stash->{tee}{$which};
168 $stash->{child}{$which} = {
169 stdin => $stash->{reader}{$which},
170 stdout => $stash->{old}{$which},
171 stderr => $stash->{capture}{$which},
173 # flag file is used to signal the child is ready
174 $stash->{flag_files}{$which} = scalar tmpnam();
175 # execute @cmd as a separate process
177 eval "use Win32API::File qw/CloseHandle GetOsFHandle SetHandleInformation fileLastError HANDLE_FLAG_INHERIT INVALID_HANDLE_VALUE/ ";
178 _debug( "# Win32API::File loaded\n") unless $@;
179 my $os_fhandle = GetOsFHandle( $stash->{tee}{$which} );
180 _debug( "# Couldn't get OS handle: " . fileLastError() . "\n") if ! defined $os_fhandle || $os_fhandle == INVALID_HANDLE_VALUE();
181 if ( SetHandleInformation( $os_fhandle, HANDLE_FLAG_INHERIT(), 0) ) {
182 _debug( "# set no-inherit flag on $which tee\n" );
185 _debug( "# can't disable tee handle flag inherit: " . fileLastError() . "\n");
187 _open_std( $stash->{child}{$which} );
188 $stash->{pid}{$which} = system(1, @cmd, $stash->{flag_files}{$which});
189 # not restoring std here as it all gets redirected again shortly anyway
192 _fork_exec( $which, $stash );
197 my ($which, $stash) = @_;
199 if ( not defined $pid ) {
200 Carp::confess "Couldn't fork(): $!";
202 elsif ($pid == 0) { # child
203 _debug( "# in child process ...\n" );
204 untie *STDIN; untie *STDOUT; untie *STDERR;
205 _close $stash->{tee}{$which};
206 _debug( "# redirecting handles in child ...\n" );
207 _open_std( $stash->{child}{$which} );
208 _debug( "# calling exec on command ...\n" );
209 exec @cmd, $stash->{flag_files}{$which};
211 $stash->{pid}{$which} = $pid
214 sub _files_exist { -f $_ || return 0 for @_; return 1 }
219 my @files = values %{$stash->{flag_files}};
220 1 until _files_exist(@files) || (time - $start > 30);
221 Carp::confess "Timed out waiting for subprocesses to start" if ! _files_exist(@files);
222 unlink $_ for @files;
228 _debug( "# closing handles with CloseHandle\n");
229 CloseHandle( GetOsFHandle($_) ) for values %{ $stash->{tee} };
230 _debug( "# waiting for subprocesses to finish\n");
232 1 until wait == -1 || (time - $start > 30);
235 _close $_ for values %{ $stash->{tee} };
236 waitpid $_, 0 for values %{ $stash->{pid} };
241 seek $_[0],0,0; local $/; return scalar readline $_[0];
244 #--------------------------------------------------------------------------#
245 # _capture_tee() -- generic main sub for capturing or teeing
246 #--------------------------------------------------------------------------#
249 _debug( "# starting _capture_tee with (@_)...\n" );
250 my ($tee_stdout, $tee_stderr, $merge, $code) = @_;
251 # save existing filehandles and setup captures
252 local *CT_ORIG_STDIN = *STDIN ;
253 local *CT_ORIG_STDOUT = *STDOUT;
254 local *CT_ORIG_STDERR = *STDERR;
255 # find initial layers
257 stdin => [PerlIO::get_layers(\*STDIN) ],
258 stdout => [PerlIO::get_layers(\*STDOUT)],
259 stderr => [PerlIO::get_layers(\*STDERR)],
261 _debug( "# existing layers for $_\: @{$layers{$_}}\n" ) for qw/stdin stdout stderr/;
262 # bypass scalar filehandles and tied handles
264 $localize{stdin}++, local(*STDIN) if grep { $_ eq 'scalar' } @{$layers{stdin}};
265 $localize{stdout}++, local(*STDOUT) if grep { $_ eq 'scalar' } @{$layers{stdout}};
266 $localize{stderr}++, local(*STDERR) if grep { $_ eq 'scalar' } @{$layers{stderr}};
267 $localize{stdout}++, local(*STDOUT), _open( \*STDOUT, ">&=1") if tied *STDOUT && $] >= 5.008;
268 $localize{stderr}++, local(*STDERR), _open( \*STDERR, ">&=2") if tied *STDERR && $] >= 5.008;
269 _debug( "# localized $_\n" ) for keys %localize;
270 my %proxy_std = _proxy_std();
271 _debug( "# proxy std is @{ [%proxy_std] }\n" );
272 my $stash = { old => _copy_std() };
273 # update layers after any proxying
275 stdin => [PerlIO::get_layers(\*STDIN) ],
276 stdout => [PerlIO::get_layers(\*STDOUT)],
277 stderr => [PerlIO::get_layers(\*STDERR)],
279 _debug( "# post-proxy layers for $_\: @{$layers{$_}}\n" ) for qw/stdin stdout stderr/;
280 # get handles for capture and apply existing IO layers
281 $stash->{new}{$_} = $stash->{capture}{$_} = File::Temp->new for qw/stdout stderr/;
282 _debug("# will capture $_ on " .fileno($stash->{capture}{$_})."\n" ) for qw/stdout stderr/;
283 # tees may change $stash->{new}
284 _start_tee( stdout => $stash ) if $tee_stdout;
285 _start_tee( stderr => $stash ) if $tee_stderr;
286 _wait_for_tees( $stash ) if $tee_stdout || $tee_stderr;
287 # finalize redirection
288 $stash->{new}{stderr} = $stash->{new}{stdout} if $merge;
289 $stash->{new}{stdin} = $stash->{old}{stdin};
290 _debug( "# redirecting in parent ...\n" );
291 _open_std( $stash->{new} );
292 # execute user provided code
295 local *STDIN = *CT_ORIG_STDIN if $localize{stdin}; # get original, not proxy STDIN
296 local *STDERR = *STDOUT if $merge; # minimize buffer mixups during $code
297 _debug( "# finalizing layers ...\n" );
298 _relayer(\*STDOUT, $layers{stdout});
299 _relayer(\*STDERR, $layers{stderr}) unless $merge;
300 _debug( "# running code $code ...\n" );
302 $exit_code = $?; # save this for later
304 # restore prior filehandles and shut down tees
305 _debug( "# restoring ...\n" );
306 _open_std( $stash->{old} );
307 _close( $_ ) for values %{$stash->{old}}; # don't leak fds
308 _unproxy( %proxy_std );
309 _kill_tees( $stash ) if $tee_stdout || $tee_stderr;
310 # return captured output
311 _relayer($stash->{capture}{stdout}, $layers{stdout});
312 _relayer($stash->{capture}{stderr}, $layers{stderr}) unless $merge;
313 _debug( "# slurping captured $_ with layers: @{[PerlIO::get_layers($stash->{capture}{$_})]}\n") for qw/stdout stderr/;
314 my $got_out = _slurp($stash->{capture}{stdout});
315 my $got_err = $merge ? q() : _slurp($stash->{capture}{stderr});
316 print CT_ORIG_STDOUT $got_out if $localize{stdout} && $tee_stdout;
317 print CT_ORIG_STDERR $got_err if !$merge && $localize{stderr} && $tee_stdout;
319 _debug( "# ending _capture_tee with (@_)...\n" );
320 return $got_out if $merge;
321 return wantarray ? ($got_out, $got_err) : $got_out;
324 #--------------------------------------------------------------------------#
325 # create API subroutines from [tee STDOUT flag, tee STDERR, merge flag]
326 #--------------------------------------------------------------------------#
330 capture_merged => [0,0,1],
332 tee_merged => [1,0,1], # don't tee STDOUT since merging
335 for my $sub ( keys %api ) {
336 my $args = join q{, }, @{$api{$sub}};
337 eval "sub $sub(&) {unshift \@_, $args; goto \\&_capture_tee;}"; ## no critic
348 Capture::Tiny - Capture STDOUT and STDERR from Perl, XS or external programs
352 This documentation describes version %%VERSION%%.
356 use Capture::Tiny qw/capture tee capture_merged tee_merged/;
358 ($stdout, $stderr) = capture {
362 ($stdout, $stderr) = tee {
366 $merged = capture_merged {
370 $merged = tee_merged {
376 Capture::Tiny provides a simple, portable way to capture anything sent to
377 STDOUT or STDERR, regardless of whether it comes from Perl, from XS code or
378 from an external program. Optionally, output can be teed so that it is
379 captured while being passed through to the original handles. Yes, it even
380 works on Windows. Stop guessing which of a dozen capturing modules to use in
381 any particular situation and just use this one.
383 This module was heavily inspired by [IO::CaptureOutput], which provides
384 similar functionality without the ability to tee output and with more
385 complicated code and API.
389 The following functions are available. None are exported by default.
393 ($stdout, $stderr) = capture \&code;
394 $stdout = capture \&code;
396 The {capture} function takes a code reference and returns what is sent to
397 STDOUT and STDERR. In scalar context, it returns only STDOUT. If no output
398 was received, returns an empty string. Regardless of context, all output is
399 captured -- nothing is passed to the existing handles.
401 It is prototyped to take a subroutine reference as an argument. Thus, it
402 can be called in block form:
404 ($stdout, $stderr) = capture {
410 $merged = capture_merged \&code;
412 The {capture_merged} function works just like {capture} except STDOUT and
413 STDERR are merged. (Technically, STDERR is redirected to STDOUT before
414 executing the function.) If no output was received, returns an empty string.
415 As with {capture} it may be called in block form.
417 Caution: STDOUT and STDERR output in the merged result are not guaranteed to be
418 properly ordered due to buffering.
422 ($stdout, $stderr) = tee \&code;
423 $stdout = tee \&code;
425 The {tee} function works just like {capture}, except that output is captured
426 as well as passed on to the original STDOUT and STDERR. As with {capture} it
427 may be called in block form.
431 $merged = tee_merged \&code;
433 The {tee_merged} function works just like {capture_merged} except that output
434 is captured as well as passed on to STDOUT. As with {capture} it may be called
437 Caution: STDOUT and STDERR output in the merged result are not guaranteed to be
438 properly ordered due to buffering.
444 Portability is a goal, not a guarantee. {tee} requires fork, except on
445 Windows where {system(1, @cmd)} is used instead. Not tested on any
446 particularly esoteric platforms yet.
450 Capture::Tiny does it's best to preserve PerlIO layers such as ':utf8' or
451 ':crlf' when capturing. Layers should be applied to STDOUT or STDERR ~before~
452 the call to {capture} or {tee}.
454 == Closed STDIN, STDOUT or STDERR
456 Capture::Tiny will work even if STDIN, STDOUT or STDERR have been previously
457 closed. However, since they may be reopened to capture or tee output, any code
458 within the captured block that depends on finding them closed will, of course,
459 not find them to be closed. If they started closed, Capture::Tiny will reclose
460 them again when the capture block finishes.
462 == Scalar filehandles and STDIN, STDOUT or STDERR
464 If STDOUT or STDERR are reopened to scalar filehandles prior to the call to
465 {capture} or {tee}, then Capture::Tiny will override the output handle for the
466 duration of the {capture} or {tee} call and then send captured output to the
467 output handle after the capture is complete. (Requires Perl 5.8)
469 Capture::Tiny attempts to preserve the semantics of STDIN opened to a scalar
472 == Tied STDIN, STDOUT or STDERR
474 If STDOUT or STDERR are tied prior to the call to {capture} or {tee}, then
475 Capture::Tiny will attempt to override the tie for the duration of the
476 {capture} or {tee} call and then send captured output to the tied handle after
477 the capture is complete. (Requires Perl 5.8)
479 Capture::Tiny does not (yet) support resending utf8 encoded data to a tied
480 STDOUT or STDERR handle. Characters will appear as bytes.
482 Capture::Tiny attempts to preserve the semantics of tied STDIN, but capturing
483 or teeing when STDIN is tied is currently broken on Windows.
485 == Modifiying STDIN, STDOUT or STDERR during a capture
487 Attempting to modify STDIN, STDOUT or STDERR ~during~ {capture} or {tee} is
488 almost certainly going to cause problems. Don't do that.
492 Please report any bugs or feature requests using the CPAN Request Tracker.
493 Bugs can be submitted through the web interface at
494 [http://rt.cpan.org/Dist/Display.html?Queue=Capture-Tiny]
496 When submitting a bug or request, please include a test-file or a patch to an
497 existing test-file that illustrates the bug or desired feature.
501 This is a selection of CPAN modules that provide some sort of output capture,
502 albeit with various limitations that make them appropriate only in particular
503 circumstances. I'm probably missing some. The long list is provided to show
504 why I felt Capture::Tiny was necessary.
507 * [IO::Capture::Extended]
508 * [IO::CaptureOutput]
513 * [IPC::Open3::Simple]
514 * [IPC::Open3::Utils]
516 * [IPC::Run::SafeHandles]
519 * [IPC::System::Simple]
530 David A. Golden (DAGOLDEN)
532 = COPYRIGHT AND LICENSE
534 Copyright (c) 2009 by David A. Golden. All rights reserved.
536 Licensed under Apache License, Version 2.0 (the "License"). You may not use
537 this file except in compliance with the License. A copy of the License was
538 distributed with this file or you may obtain a copy of the License from
539 http://www.apache.org/licenses/LICENSE-2.0
541 Files produced as output though the use of this software, shall not be
542 considered Derivative Works, but shall be considered the original work of the
545 Unless required by applicable law or agreed to in writing, software
546 distributed under the License is distributed on an "AS IS" BASIS,
547 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
548 See the License for the specific language governing permissions and
549 limitations under the License.