Blame README

Packit d18d0a
NAME
Packit d18d0a
    Capture::Tiny - Capture STDOUT and STDERR from Perl, XS or external
Packit d18d0a
    programs
Packit d18d0a
Packit d18d0a
VERSION
Packit d18d0a
    version 0.46
Packit d18d0a
Packit d18d0a
SYNOPSIS
Packit d18d0a
      use Capture::Tiny ':all';
Packit d18d0a
Packit d18d0a
      # capture from external command
Packit d18d0a
Packit d18d0a
      ($stdout, $stderr, $exit) = capture {
Packit d18d0a
        system( $cmd, @args );
Packit d18d0a
      };
Packit d18d0a
Packit d18d0a
      # capture from arbitrary code (Perl or external)
Packit d18d0a
Packit d18d0a
      ($stdout, $stderr, @result) = capture {
Packit d18d0a
        # your code here
Packit d18d0a
      };
Packit d18d0a
Packit d18d0a
      # capture partial or merged output
Packit d18d0a
Packit d18d0a
      $stdout = capture_stdout { ... };
Packit d18d0a
      $stderr = capture_stderr { ... };
Packit d18d0a
      $merged = capture_merged { ... };
Packit d18d0a
Packit d18d0a
      # tee output
Packit d18d0a
Packit d18d0a
      ($stdout, $stderr) = tee {
Packit d18d0a
        # your code here
Packit d18d0a
      };
Packit d18d0a
Packit d18d0a
      $stdout = tee_stdout { ... };
Packit d18d0a
      $stderr = tee_stderr { ... };
Packit d18d0a
      $merged = tee_merged { ... };
Packit d18d0a
Packit d18d0a
DESCRIPTION
Packit d18d0a
    Capture::Tiny provides a simple, portable way to capture almost anything
Packit d18d0a
    sent to STDOUT or STDERR, regardless of whether it comes from Perl, from
Packit d18d0a
    XS code or from an external program. Optionally, output can be teed so
Packit d18d0a
    that it is captured while being passed through to the original
Packit d18d0a
    filehandles. Yes, it even works on Windows (usually). Stop guessing
Packit d18d0a
    which of a dozen capturing modules to use in any particular situation
Packit d18d0a
    and just use this one.
Packit d18d0a
Packit d18d0a
USAGE
Packit d18d0a
    The following functions are available. None are exported by default.
Packit d18d0a
Packit d18d0a
  capture
Packit d18d0a
      ($stdout, $stderr, @result) = capture \&cod;;
Packit d18d0a
      $stdout = capture \&cod;;
Packit d18d0a
Packit d18d0a
    The "capture" function takes a code reference and returns what is sent
Packit d18d0a
    to STDOUT and STDERR as well as any return values from the code
Packit d18d0a
    reference. In scalar context, it returns only STDOUT. If no output was
Packit d18d0a
    received for a filehandle, it returns an empty string for that
Packit d18d0a
    filehandle. Regardless of calling context, all output is captured --
Packit d18d0a
    nothing is passed to the existing filehandles.
Packit d18d0a
Packit d18d0a
    It is prototyped to take a subroutine reference as an argument. Thus, it
Packit d18d0a
    can be called in block form:
Packit d18d0a
Packit d18d0a
      ($stdout, $stderr) = capture {
Packit d18d0a
        # your code here ...
Packit d18d0a
      };
Packit d18d0a
Packit d18d0a
    Note that the coderef is evaluated in list context. If you wish to force
Packit d18d0a
    scalar context on the return value, you must use the "scalar" keyword.
Packit d18d0a
Packit d18d0a
      ($stdout, $stderr, $count) = capture {
Packit d18d0a
        my @list = qw/one two three/;
Packit d18d0a
        return scalar @list; # $count will be 3
Packit d18d0a
      };
Packit d18d0a
Packit d18d0a
    Also note that within the coderef, the @_ variable will be empty. So
Packit d18d0a
    don't use arguments from a surrounding subroutine without copying them
Packit d18d0a
    to an array first:
Packit d18d0a
Packit d18d0a
      sub wont_work {
Packit d18d0a
        my ($stdout, $stderr) = capture { do_stuff( @_ ) };    # WRONG
Packit d18d0a
        ...
Packit d18d0a
      }
Packit d18d0a
Packit d18d0a
      sub will_work {
Packit d18d0a
        my @args = @_;
Packit d18d0a
        my ($stdout, $stderr) = capture { do_stuff( @args ) }; # RIGHT
Packit d18d0a
        ...
Packit d18d0a
      }
Packit d18d0a
Packit d18d0a
    Captures are normally done to an anonymous temporary filehandle. To
Packit d18d0a
    capture via a named file (e.g. to externally monitor a long-running
Packit d18d0a
    capture), provide custom filehandles as a trailing list of option pairs:
Packit d18d0a
Packit d18d0a
      my $out_fh = IO::File->new("out.txt", "w+");
Packit d18d0a
      my $err_fh = IO::File->new("out.txt", "w+");
Packit d18d0a
      capture { ... } stdout => $out_fh, stderr => $err_fh;
Packit d18d0a
Packit d18d0a
    The filehandles must be read/write and seekable. Modifying the files or
Packit d18d0a
    filehandles during a capture operation will give unpredictable results.
Packit d18d0a
    Existing IO layers on them may be changed by the capture.
Packit d18d0a
Packit d18d0a
    When called in void context, "capture" saves memory and time by not
Packit d18d0a
    reading back from the capture handles.
Packit d18d0a
Packit d18d0a
  capture_stdout
Packit d18d0a
      ($stdout, @result) = capture_stdout \&cod;;
Packit d18d0a
      $stdout = capture_stdout \&cod;;
Packit d18d0a
Packit d18d0a
    The "capture_stdout" function works just like "capture" except only
Packit d18d0a
    STDOUT is captured. STDERR is not captured.
Packit d18d0a
Packit d18d0a
  capture_stderr
Packit d18d0a
      ($stderr, @result) = capture_stderr \&cod;;
Packit d18d0a
      $stderr = capture_stderr \&cod;;
Packit d18d0a
Packit d18d0a
    The "capture_stderr" function works just like "capture" except only
Packit d18d0a
    STDERR is captured. STDOUT is not captured.
Packit d18d0a
Packit d18d0a
  capture_merged
Packit d18d0a
      ($merged, @result) = capture_merged \&cod;;
Packit d18d0a
      $merged = capture_merged \&cod;;
Packit d18d0a
Packit d18d0a
    The "capture_merged" function works just like "capture" except STDOUT
Packit d18d0a
    and STDERR are merged. (Technically, STDERR is redirected to the same
Packit d18d0a
    capturing handle as STDOUT before executing the function.)
Packit d18d0a
Packit d18d0a
    Caution: STDOUT and STDERR output in the merged result are not
Packit d18d0a
    guaranteed to be properly ordered due to buffering.
Packit d18d0a
Packit d18d0a
  tee
Packit d18d0a
      ($stdout, $stderr, @result) = tee \&cod;;
Packit d18d0a
      $stdout = tee \&cod;;
Packit d18d0a
Packit d18d0a
    The "tee" function works just like "capture", except that output is
Packit d18d0a
    captured as well as passed on to the original STDOUT and STDERR.
Packit d18d0a
Packit d18d0a
    When called in void context, "tee" saves memory and time by not reading
Packit d18d0a
    back from the capture handles, except when the original STDOUT OR STDERR
Packit d18d0a
    were tied or opened to a scalar handle.
Packit d18d0a
Packit d18d0a
  tee_stdout
Packit d18d0a
      ($stdout, @result) = tee_stdout \&cod;;
Packit d18d0a
      $stdout = tee_stdout \&cod;;
Packit d18d0a
Packit d18d0a
    The "tee_stdout" function works just like "tee" except only STDOUT is
Packit d18d0a
    teed. STDERR is not teed (output goes to STDERR as usual).
Packit d18d0a
Packit d18d0a
  tee_stderr
Packit d18d0a
      ($stderr, @result) = tee_stderr \&cod;;
Packit d18d0a
      $stderr = tee_stderr \&cod;;
Packit d18d0a
Packit d18d0a
    The "tee_stderr" function works just like "tee" except only STDERR is
Packit d18d0a
    teed. STDOUT is not teed (output goes to STDOUT as usual).
Packit d18d0a
Packit d18d0a
  tee_merged
Packit d18d0a
      ($merged, @result) = tee_merged \&cod;;
Packit d18d0a
      $merged = tee_merged \&cod;;
Packit d18d0a
Packit d18d0a
    The "tee_merged" function works just like "capture_merged" except that
Packit d18d0a
    output is captured as well as passed on to STDOUT.
Packit d18d0a
Packit d18d0a
    Caution: STDOUT and STDERR output in the merged result are not
Packit d18d0a
    guaranteed to be properly ordered due to buffering.
Packit d18d0a
Packit d18d0a
LIMITATIONS
Packit d18d0a
  Portability
Packit d18d0a
    Portability is a goal, not a guarantee. "tee" requires fork, except on
Packit d18d0a
    Windows where "system(1, @cmd)" is used instead. Not tested on any
Packit d18d0a
    particularly esoteric platforms yet. See the CPAN Testers Matrix
Packit d18d0a
    <http://matrix.cpantesters.org/?dist=Capture-Tiny> for test result by
Packit d18d0a
    platform.
Packit d18d0a
Packit d18d0a
  PerlIO layers
Packit d18d0a
    Capture::Tiny does its best to preserve PerlIO layers such as ':utf8' or
Packit d18d0a
    ':crlf' when capturing (only for Perl 5.8.1+) . Layers should be applied
Packit d18d0a
    to STDOUT or STDERR *before* the call to "capture" or "tee". This may
Packit d18d0a
    not work for tied filehandles (see below).
Packit d18d0a
Packit d18d0a
  Modifying filehandles before capturing
Packit d18d0a
    Generally speaking, you should do little or no manipulation of the
Packit d18d0a
    standard IO filehandles prior to using Capture::Tiny. In particular,
Packit d18d0a
    closing, reopening, localizing or tying standard filehandles prior to
Packit d18d0a
    capture may cause a variety of unexpected, undesirable and/or unreliable
Packit d18d0a
    behaviors, as described below. Capture::Tiny does its best to compensate
Packit d18d0a
    for these situations, but the results may not be what you desire.
Packit d18d0a
Packit d18d0a
   Closed filehandles
Packit d18d0a
    Capture::Tiny will work even if STDIN, STDOUT or STDERR have been
Packit d18d0a
    previously closed. However, since they will be reopened to capture or
Packit d18d0a
    tee output, any code within the captured block that depends on finding
Packit d18d0a
    them closed will, of course, not find them to be closed. If they started
Packit d18d0a
    closed, Capture::Tiny will close them again when the capture block
Packit d18d0a
    finishes.
Packit d18d0a
Packit d18d0a
    Note that this reopening will happen even for STDIN or a filehandle not
Packit d18d0a
    being captured to ensure that the filehandle used for capture is not
Packit d18d0a
    opened to file descriptor 0, as this causes problems on various
Packit d18d0a
    platforms.
Packit d18d0a
Packit d18d0a
    Prior to Perl 5.12, closed STDIN combined with PERL_UNICODE=D leaks
Packit d18d0a
    filehandles and also breaks tee() for undiagnosed reasons. So don't do
Packit d18d0a
    that.
Packit d18d0a
Packit d18d0a
   Localized filehandles
Packit d18d0a
    If code localizes any of Perl's standard filehandles before capturing,
Packit d18d0a
    the capture will affect the localized filehandles and not the original
Packit d18d0a
    ones. External system calls are not affected by localizing a filehandle
Packit d18d0a
    in Perl and will continue to send output to the original filehandles
Packit d18d0a
    (which will thus not be captured).
Packit d18d0a
Packit d18d0a
   Scalar filehandles
Packit d18d0a
    If STDOUT or STDERR are reopened to scalar filehandles prior to the call
Packit d18d0a
    to "capture" or "tee", then Capture::Tiny will override the output
Packit d18d0a
    filehandle for the duration of the "capture" or "tee" call and then, for
Packit d18d0a
    "tee", send captured output to the output filehandle after the capture
Packit d18d0a
    is complete. (Requires Perl 5.8)
Packit d18d0a
Packit d18d0a
    Capture::Tiny attempts to preserve the semantics of STDIN opened to a
Packit d18d0a
    scalar reference, but note that external processes will not be able to
Packit d18d0a
    read from such a handle. Capture::Tiny tries to ensure that external
Packit d18d0a
    processes will read from the null device instead, but this is not
Packit d18d0a
    guaranteed.
Packit d18d0a
Packit d18d0a
   Tied output filehandles
Packit d18d0a
    If STDOUT or STDERR are tied prior to the call to "capture" or "tee",
Packit d18d0a
    then Capture::Tiny will attempt to override the tie for the duration of
Packit d18d0a
    the "capture" or "tee" call and then send captured output to the tied
Packit d18d0a
    filehandle after the capture is complete. (Requires Perl 5.8)
Packit d18d0a
Packit d18d0a
    Capture::Tiny may not succeed resending UTF-8 encoded data to a tied
Packit d18d0a
    STDOUT or STDERR filehandle. Characters may appear as bytes. If the tied
Packit d18d0a
    filehandle is based on Tie::StdHandle, then Capture::Tiny will attempt
Packit d18d0a
    to determine appropriate layers like ":utf8" from the underlying
Packit d18d0a
    filehandle and do the right thing.
Packit d18d0a
Packit d18d0a
   Tied input filehandle
Packit d18d0a
    Capture::Tiny attempts to preserve the semantics of tied STDIN, but this
Packit d18d0a
    requires Perl 5.8 and is not entirely predictable. External processes
Packit d18d0a
    will not be able to read from such a handle.
Packit d18d0a
Packit d18d0a
    Unless having STDIN tied is crucial, it may be safest to localize STDIN
Packit d18d0a
    when capturing:
Packit d18d0a
Packit d18d0a
      my ($out, $err) = do { local *STDIN; capture { ... } };
Packit d18d0a
Packit d18d0a
  Modifying filehandles during a capture
Packit d18d0a
    Attempting to modify STDIN, STDOUT or STDERR *during* "capture" or "tee"
Packit d18d0a
    is almost certainly going to cause problems. Don't do that.
Packit d18d0a
Packit d18d0a
   Forking inside a capture
Packit d18d0a
    Forks aren't portable. The behavior of filehandles during a fork is even
Packit d18d0a
    less so. If Capture::Tiny detects that a fork has occurred within a
Packit d18d0a
    capture, it will shortcut in the child process and return empty strings
Packit d18d0a
    for captures. Other problems may occur in the child or parent, as well.
Packit d18d0a
    Forking in a capture block is not recommended.
Packit d18d0a
Packit d18d0a
   Using threads
Packit d18d0a
    Filehandles are global. Mixing up I/O and captures in different threads
Packit d18d0a
    without coordination is going to cause problems. Besides, threads are
Packit d18d0a
    officially discouraged.
Packit d18d0a
Packit d18d0a
   Dropping privileges during a capture
Packit d18d0a
    If you drop privileges during a capture, temporary files created to
Packit d18d0a
    facilitate the capture may not be cleaned up afterwards.
Packit d18d0a
Packit d18d0a
  No support for Perl 5.8.0
Packit d18d0a
    It's just too buggy when it comes to layers and UTF-8. Perl 5.8.1 or
Packit d18d0a
    later is recommended.
Packit d18d0a
Packit d18d0a
  Limited support for Perl 5.6
Packit d18d0a
    Perl 5.6 predates PerlIO. UTF-8 data may not be captured correctly.
Packit d18d0a
Packit d18d0a
ENVIRONMENT
Packit d18d0a
  PERL_CAPTURE_TINY_TIMEOUT
Packit d18d0a
    Capture::Tiny uses subprocesses internally for "tee". By default,
Packit d18d0a
    Capture::Tiny will timeout with an error if such subprocesses are not
Packit d18d0a
    ready to receive data within 30 seconds (or whatever is the value of
Packit d18d0a
    $Capture::Tiny::TIMEOUT). An alternate timeout may be specified by
Packit d18d0a
    setting the "PERL_CAPTURE_TINY_TIMEOUT" environment variable. Setting it
Packit d18d0a
    to zero will disable timeouts. NOTE, this does not timeout the code
Packit d18d0a
    reference being captured -- this only prevents Capture::Tiny itself from
Packit d18d0a
    hanging your process waiting for its child processes to be ready to
Packit d18d0a
    proceed.
Packit d18d0a
Packit d18d0a
SEE ALSO
Packit d18d0a
    This module was inspired by IO::CaptureOutput, which provides similar
Packit d18d0a
    functionality without the ability to tee output and with more
Packit d18d0a
    complicated code and API. IO::CaptureOutput does not handle layers or
Packit d18d0a
    most of the unusual cases described in the "Limitations" section and I
Packit d18d0a
    no longer recommend it.
Packit d18d0a
Packit d18d0a
    There are many other CPAN modules that provide some sort of output
Packit d18d0a
    capture, albeit with various limitations that make them appropriate only
Packit d18d0a
    in particular circumstances. I'm probably missing some. The long list is
Packit d18d0a
    provided to show why I felt Capture::Tiny was necessary.
Packit d18d0a
Packit d18d0a
    *   IO::Capture
Packit d18d0a
Packit d18d0a
    *   IO::Capture::Extended
Packit d18d0a
Packit d18d0a
    *   IO::CaptureOutput
Packit d18d0a
Packit d18d0a
    *   IPC::Capture
Packit d18d0a
Packit d18d0a
    *   IPC::Cmd
Packit d18d0a
Packit d18d0a
    *   IPC::Open2
Packit d18d0a
Packit d18d0a
    *   IPC::Open3
Packit d18d0a
Packit d18d0a
    *   IPC::Open3::Simple
Packit d18d0a
Packit d18d0a
    *   IPC::Open3::Utils
Packit d18d0a
Packit d18d0a
    *   IPC::Run
Packit d18d0a
Packit d18d0a
    *   IPC::Run::SafeHandles
Packit d18d0a
Packit d18d0a
    *   IPC::Run::Simple
Packit d18d0a
Packit d18d0a
    *   IPC::Run3
Packit d18d0a
Packit d18d0a
    *   IPC::System::Simple
Packit d18d0a
Packit d18d0a
    *   Tee
Packit d18d0a
Packit d18d0a
    *   IO::Tee
Packit d18d0a
Packit d18d0a
    *   File::Tee
Packit d18d0a
Packit d18d0a
    *   Filter::Handle
Packit d18d0a
Packit d18d0a
    *   Tie::STDERR
Packit d18d0a
Packit d18d0a
    *   Tie::STDOUT
Packit d18d0a
Packit d18d0a
    *   Test::Output
Packit d18d0a
Packit d18d0a
SUPPORT
Packit d18d0a
  Bugs / Feature Requests
Packit d18d0a
    Please report any bugs or feature requests through the issue tracker at
Packit d18d0a
    <https://github.com/dagolden/Capture-Tiny/issues>. You will be notified
Packit d18d0a
    automatically of any progress on your issue.
Packit d18d0a
Packit d18d0a
  Source Code
Packit d18d0a
    This is open source software. The code repository is available for
Packit d18d0a
    public review and contribution under the terms of the license.
Packit d18d0a
Packit d18d0a
    <https://github.com/dagolden/Capture-Tiny>
Packit d18d0a
Packit d18d0a
      git clone https://github.com/dagolden/Capture-Tiny.git
Packit d18d0a
Packit d18d0a
AUTHOR
Packit d18d0a
    David Golden <dagolden@cpan.org>
Packit d18d0a
Packit d18d0a
CONTRIBUTORS
Packit d18d0a
    *   Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Packit d18d0a
Packit d18d0a
    *   David E. Wheeler <david@justatheory.com>
Packit d18d0a
Packit d18d0a
    *   fecundf <not.com+github@gmail.com>
Packit d18d0a
Packit d18d0a
    *   Graham Knop <haarg@haarg.org>
Packit d18d0a
Packit d18d0a
    *   Peter Rabbitson <ribasushi@cpan.org>
Packit d18d0a
Packit d18d0a
COPYRIGHT AND LICENSE
Packit d18d0a
    This software is Copyright (c) 2009 by David Golden.
Packit d18d0a
Packit d18d0a
    This is free software, licensed under:
Packit d18d0a
Packit d18d0a
      The Apache License, Version 2.0, January 2004
Packit d18d0a