Blame README

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