NAME
IPC::Capture - portably run external apps and capture the output
SYNOPSIS
use IPC::Capture;
my $ich = IPC::Capture->new();
$ich->set_filter('stdout_only');
my $output = $ich->run( $this_cmd );
if ( $output ) ) {
# work with $output...
}
unless( $ich->can_run( $another_cmd ) {
die "Will not be able to run the external command: $another_cmd\n";
}
$ich->set_filter('stderr_only');
my $errors = $ich->run( $another_cmd );
# stdout and stderr together:
$ich->set_filter('all_output');
my $all = $ich->run( $another_cmd );
DESCRIPTION
IPC::Capture is a module for running external applications in a portable fashion when you're primarily interested in capturing the returned output.
Essentially this is an attempt at creating a portable way of doing "backticks" with io-redirection. In fact, if it looks like it will work, this module will internally just try to run the command via a sub-shell invoked by qx; otherwise, it will try some other approaches which may work (going through other modules such as IPC::Cmd, IPC::Run, and/or IPC::Open3).
The different ways of running external commands are called "ways" here (because words like "methods" already have too many other associations). At present, there are only two "ways" defined in this module: "qx" and "ipc_cmd". We probe the system trying each of the known ways (in the order defined in the "ways" attribute), and use the first one that looks like it will work.
METHODS
- new
-
Creates a new IPC::Capture object.
Takes a hashref as an argument, with named fields identical to the names of the object attributes (which also may be set later via the accessor methods). These attributes are:
- filter
-
The "filter" is a code that specifies what command output streams we're interested in capturing. Allowed values:
- stdout_only
-
Discards stderr and returns only stdout. Like the Bourne shell redirect: '2>/dev/null'
- stderr_only
-
Discards stdout and returns only stderr. Like the Bourne shell redirect: '2>&1 1>/dev/null'
- all_output
-
Intermixes lines of stdout and stderr in chronological order. Like the Bourne shell redirect: '2>&1'
- all_separated
-
The return will be an array reference with two elements: stdout and stderr. (But under some circumstances, it may not be possible to seperate the two, and all output will be returned intermixed, as the first item, and the second will be undef.)
- autochomp
-
Set to a true value, causes all returned values to be automatically chomped. Defaults to false.
- known_ways
-
List of known ways of invoking external commands, in the default order in which they'll be tried (as of this writing: ['ex', 'ipc_cmd'].
- ways
-
List of ways of invoking external commands, in the order the user would like to try them. Defaults to "known_ways".
- way
-
The chosen "way" that will be used for invoking external commands.
- stdout_probe_messages
-
List of messages which are sent to STDOUT by the probe sub-script. An array reference.
- stderr_probe_messages
-
List of messages which are sent to STDERR by the probe sub-script. An array reference.
Takes an optional hashref as an argument, with named fields identical to the names of the object attributes.
- init
-
Method that initializes object attributes and then locks them down to prevent accidental creation of new ones.
Any class that inherits from this one should have an init of it's own that calls this init. Otherwise, it's an internally used routine that is not of much interest to client coders.
- probe_system
-
Internally used during the init phase of object creation. Chooses a good "way" of running commands external to perl.
- define_yammer_script
-
This is an internally used routine, broken out as a method for ease of testing.
This generates some code for the 'yammer_script' which is used used by "probe_system" to check which ways work for running external commands. The 'yammer_script' sends three lines of output to stdout, and if provided with command-line arguments, it will echo up to three of them to stderr. The stderr output is interleaved with the output sent to stdout, starting with stdout (so the pattern is: OeOeOe).
This method uses the object data "stdout_probe_messages" to get an aref of messages to send to stdout; but this can be overridden by passing it an aref of alternate messages.
So, just to make it clear: the STDOUT strings are defined when this method is called, but the STDERR strings are defined only when the yammer script it generates is run.
- probe_system_qx
-
Method used internally by the internal method "probe_system". Takes one argument: the script name, which it will try to run via qx.
- probe_system_ipc_cmd
-
Method used internally by the internal method "probe_system". Takes one argument: the script name, which it will try to run via IPC::Cmd.
- can_run
-
Given the name of an external command, will check to see if we can run it.
Note: just because the program has the name you're looking for, there's no guarantee that it's the right program.
- can_run_qx
-
This is a method used internally by "can_run", it tries to determine if the given program can be run via the shell (i.e. the "qx" way), and returns the full path to the program if it's found, otherwise, undef.
- can_run_qx_which
-
This is a method used internally by "can_run_qx". It uses the old old unix utility "which" to look for the given program.
- can_run_qx_path_glob
-
This is a method used internally by "can_run_qx". It looks for the given program by checking looking for an executible file of that name somewhere in the path.
- can_run_ipc_cmd
-
Given the name of a program, checks to see if it can run it. Returns the full path to the binary if it is found.
Note: this is a simple wrapper around IPC::Cmd::can_run.
- run
-
Takes one argument: an external command string.
Returns the output from the external command (as controlled by the "filter" setting in the object). The output will almost always be in the form of a multi-line string, except in one case:
If filter is set to "all_separated", then this will return a reference to an array of two elements, the first containing stdout, the second stderr.
"run_<way>_<od>"
These methods are for internal use by the "run" method.
"run_qx_*" methods
These are methods that take the given command and simply try to run them via whatever shell is available to the qx{} operator.
The "filter" setting is converted to equivalent Bourne shell redirect.
- run_qx_all_output
- run_qx_stdout_only
- run_qx_stderr_only
- run_qx_all_separated_old
-
(An earlier attempt that seemed "more correct" to me, but doesn't work on MSwin32.)
- run_qx_all_separated
"run_ipc_cmd_*" methods
These are methods that take the given command and try to run them via the IPC::Cmd module, (which in turn will try to use IPC::Run or Run::Open3).
The "filter" setting determines what kind of IPC::Cmd call to use, and which of it's output channels will be returned.
- run_ipc_cmd_stdout_only
-
Used internally by "run" when the "filter" is set to 'stdout_only' (and the "way" is 'ipc_cmd').
- run_ipc_cmd_stderr_only
-
Used internally by "run" when the "filter" is set to 'stderr_only' (and the "way" is 'ipc_cmd'):
- run_ipc_cmd_all_output
-
Used internally by "run" when the "filter" is set to 'all_output' (and the "way" is 'ipc_cmd'):
- run_ipc_cmd_all_separated
-
Used internally by "run" when the "filter" is set to 'all_separated' (and the "way" is 'ipc_cmd'):
utility methods
- chomp_aref
-
Like "chomp", but presumes it's been given an array reference of strings to work on.
basic setters and getters
The naming convention in use here is that setters begin with "set_", but getters have *no* prefix: the most commonly used case deserves the simplest syntax (and mutators are deprecated).
These accessors exist for all of the object attributes (documented above) irrespective of whether they're expected to be externally useful.
automatic generation of accessors
- AUTOLOAD
How It Works
Where possible, IPC::Capture will simply work by running the given command in a sub-shell, invoked with a qx.
During the init phase, it tries to determine if a qx works as expected (using Bourne-shell style redirects) by the expedient of writing a temporary perl script that generates a known output, and then just trying to run the script. (This step will be skipped if the object is told which style of i/o it should use when instantiated.)
It appears that qx with i/o re-direction is a relatively portable idiom these days: it's supported by most forms of perl on Windows, and I would be surprised if OSX does not support it also.
If a qx fails, then this system will try another way of doing the job using the IPC::Cmd module.
If no way of running a simple command and capturing it's output can be found, an error will be signalled during instantiation.
IPC::Cmd in turn uses IPC::Run or IPC::Open3 (depending on which is installed), which means that this module should have a fair degree of cross-platform portability.
further notes
Depending on the type of output requested with the "filter", this module will choose to do either a scalar or an array context call to IPC::Cmd::run (insulating the user from one of IPC::Cmd's oddities).
MOTIVATION
The original goal was to find something more portable than shelling out via qx with Bourne shell redirection.
I'd just written the Emacs::Run module that shells out to emacs, and I was looking for improvements. (Note: emacs is a widely available program, with portability roughly on the same scale as perl.)
The IPC::Cmd module looked like a promising simplification over directly using IPC::Run or IPC::Open3, but it's output capture features seemed clumsy.
So: my first thought was to write a wrapper around the wrapper, and as an added bonus, it would fall back on doing a simple qx if IPC::Cmd wasn't going to work.
My initial tests of that code immediately revealed a problem with IPC::Cmd: it usually worked as expected, but sometimes would behave strangely (e.g. returning only one line of output instead of the expected six; or instead of interleaving stderr with stdout, it might return all stderr lines first). My suspicion was that this was due to running on a perl with threads enabled, but in any case, it didn't inspire confidence with the idea that IPC::Cmd was going to be more reliable than qx.
At which point, it occured to me that I could rewrite the module to work the other way around: just use qx, but fall back on IPC::Cmd. And indeed, it wasn't that difficult to write probe routines to find out if qx works reliably.
All of this work seemed a little besides the point when I realized that nearly every Windows installation of perl can deal with Bourne shell redirects -- but still this module may very well improve portability to some of the more unusual platforms such as VMS or the older Macs.
And at the very least, if I use this module religiously, I can stop worrying about mistyping '2>&1'.
TODO
o More filters -- "output_to_file", etc. Add a general purpose, user-defineable one?
o IPC::Cmd seems to have reliability problems (possibly, with multi-threaded perls?), the precise output it returns can vary from run to run. Possibly: implement a voting algorithm, return the output most commonly recieved.
o Better test coverage: autochomp; probe_system*;
o 02-can_run.t tests multiple internal routines, only one flavor of which need work for the overall behavior to work. Possibly should ship only with tests that verify the interface methods...
o IPC::Capture lacks "success", as of 0.05. This means the SYNOPSIS is complete nonsense for versions 0.04 and earlier. For now, not mentioning "success", but think about implementing it.
SEE ALSO
Shell redirection apparently works on Windows: http://www.perlmonks.org/?node_id=679842
AUTHOR
Joseph Brenner, <doom@kzsu.stanford.edu>, 07 Apr 2008
COPYRIGHT AND LICENSE
Copyright (C) 2008 by Joseph Brenner
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.2 or, at your option, any later version of Perl 5 you may have available.
BUGS AND LIMITATIONS
There are possible security gotchas with using this module, because it hands strings off to the shell to execute. Any commands built-up from user input should be scrubbed carefully before being run with this module. Using taint is strongly recommended: see perlsec.