How do you capture stderr, stdout, and the exit code all at once, in Perl? - perl

Is it possible to run an external process from Perl, capture its stderr, stdout AND the process exit code?
I seem to be able to do combinations of these, e.g. use backticks to get stdout, IPC::Open3 to capture outputs, and system() to get exit codes.
How do you capture stderr, stdout, and the exit code all at once?

(Update: I updated the API for IO::CaptureOutput to make this even easier.)
There are several ways to do this. Here's one option, using the IO::CaptureOutput module:
use IO::CaptureOutput qw/capture_exec/;
my ($stdout, $stderr, $success, $exit_code) = capture_exec( #cmd );
This is the capture_exec() function, but IO::CaptureOutput also has a more general capture() function that can be used to capture either Perl output or output from external programs. So if some Perl module happens to use some external program, you still get the output.
It also means you only need to remember one single approach to capturing STDOUT and STDERR (or merging them) instead of using IPC::Open3 for external programs and other modules for capturing Perl output.

If you reread the documentation for IPC::Open3, you'll see a note that you should call waitpid to reap the child process. Once you do this, the status should be available in $?. The exit value is $? >> 8. See
$? in perldoc perlvar.

If you don't want the contents of STDERR, then the capture() command from IPC::System::Simple module is almost exactly what you're after:
use IPC::System::Simple qw(capture system $EXITVAL);
my $output = capture($cmd, #args);
my $exit_value = $EXITVAL;
You can use capture() with a single argument to invoke the shell, or multiple arguments to reliably avoid the shell. There's also capturex() which never calls the shell, even with a single argument.
Unlike Perl's built-in system and backticks commands, IPC::System::Simple returns the full 32-bit exit value under Windows. It also throws a detailed exception if the command can't be started, dies to a signal, or returns an unexpected exit value. This means for many programs, rather than checking the exit values yourself, you can rely upon
IPC::System::Simple to do the hard work for you:
use IPC::System::Simple qw(system capture $EXIT_ANY);
system( [0,1], "frobincate", #files); # Must return exitval 0 or 1
my #lines = capture($EXIT_ANY, "baznicate", #files); # Any exitval is OK.
foreach my $record (#lines) {
system( [0, 32], "barnicate", $record); # Must return exitval 0 or 32
}
IPC::System::Simple is pure Perl, has no dependencies, and works on both Unix and Windows systems. Unfortunately, it doesn't provide a way of capturing STDERR, so it may not be suitable for all your needs.
IPC::Run3 provides a clean and easy interface into re-plumbing all three common filehandles, but unfortunately it doesn't check to see if the command was successful, so you'll need to inspect $? manually, which is not at all fun. Providing a public interface for inspecting $? is something which is on my to-do list for IPC::System::Simple, since inspecting $? in a cross-platform fashion is not a task I'd wish on anyone.
There are other modules in the IPC:: namespace that may also provide you with assistance. YMMV.
All the best,
Paul

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's STDOUT and STDERR, unless the system() command redirects them. Backticks and open() read only the STDOUT of your command.
You could also call something like the following with open to redirect both STDOUT and STDERR.
open(PIPE, "cmd 2>&1 |");
The return code is always stored in $? as noted by #Michael Carman.

If you're getting really complicated, you might want to try Expect.pm. But that's probably overkill if you don't need to also manage sending input to the process as well.

I found IPC:run3 to be very helpful. You can forward all child pipes to a glob or a variable; very easily! And exit code will be stored in $?.
Below is how i grabbed stderr which i knew would be a number. The cmd output informatic transformations to stdout (which i piped to a file in the args using >) and reported how many transformations to STDERR.
use IPC::Run3
my $number;
my $run = run3("cmd arg1 arg2 >output_file",\undef, \undef, \$number);
die "Command failed: $!" unless ($run && $? == 0);

Related

I have a system call that somehow is causing malformed header from script Bad header

I have a Perl CGI program. myperlcgi.pl
Within this program I have the following:
my $retval = system('extprogram')
extprogram has a print statement within.
The output from extprogram is being included within myperlcgi.pl
I tried adding
> output.txt 2>&1
to system call but did not change anything.
How do I prevent output form extprogram being used in myperlcgi.pl.
Surprised that stdout from system call is being used in myperlcgi.pl
The system command just doesn’t give you complete control over capturing STDOUT and STDERR of the executed command.
Use backticks or open to execute the command instead. That will capture the STDOUT of the command’s execution. If the command also outputs to STDERR, then you can append 2>&1 to redirect STDERR to STDOUT for capture in backticks, like so:
my $output = `$command 2>&1`;
If you really need the native return status of the executed command, you can get that information using $? or ${^CHILD_ERROR_NATIVE}. See perldoc perlvar for details.
Another option is to use the IPC::Open3 Perl library, but I find that method to be overkill for most situations.

command output is directed to the screen

novice Perl programmer here!.
I'm using the system() function to get the return code for an external program (in this case - php), however, the command's output is still printed to the screen.
How do I prevent it from doing so?
My code is:
use strict; use warnings;
print 'Return code:', system('php -l wrong.php'), "\n";
This code does print the return code, but it also print the the output of the command executed.
Any help will be appreciated!
EDIT: further testing shown that this happens while only using the php lint command.. using it with other commands doesnt print anything...
What you want is IPC::Open3:
use IPC::Open3;
use Symbol qw(gensym);
my $err = gensym; #work around IPC::Open3's interface
my $pid = open3 my $wtr, my $rdr, $err,
'some cmd', 'arg1', 'arg2', ...;
The separates out stdin into $wtr, stdout into $rdr, and stderr into $err
This also gives you maximum control over communicating with the process
If you are on a UNIX-like OS, you should be able to redirect the output in the command:
Try:
system('php -l wrong.php >> /dev/null') to get rid of what's being sent to stdout.
You could also open the command with a pipe to handle the output directly, which should be more portable.

How can I check the status of the first program in pipeline in Perl's system()?

perl -e 'system ("crontab1 -l");print $?'
returns -1 as expected (program crontab1 doesn't exist)
perl -e 'system ("crontab1 -l|grep blah");print $?'
returns 256.
What is the way to check the status of the first (or both) programs?
You are getting the exit status of the entire command, just as you should. If you want the exit status separately, you're going to have to run the commands separately.
#!/usr/bin/perl -e
system("crontab1 -l > /tmp/junk.txt"); print $?;
system("grep blah /tmp/junk.txt"); print $?;
as an example.
If you tolerate using something other than system, there are easier solutions. For example, the results method in IPC::Run returns all exit codes of the chain.
Remember, you're supposed to use $?>>8 to get the exit code, not $?
perl -e 'system("set -o pipefail;false | true");print $?>>8,"\n"'
1
This ("pipefail") only works if your shell is bash 3. Cygwin and some Linux flavors ship with it; not sure about mac.
You should be aware that 256 is an error return. 0 is what you'd get on success:
perl -e 'system("true");print $?>>8,"\n"'
0
I didn't know system returned -1 for a single command that isn't found, but $?>>8 should still be non-zero in that case.
[This was composed as an answer to another question which was closed as a duplicate of this one.]
Executing a shell command requires executing a shell. To that end,
system($shell_command)
is equivalent to
system('/bin/sh', '-c', $shell_command)
As such, all of your examples run a single program (/bin/sh). If you want the exit statuses of multiple children, you're going to need to have multiple children!
use IPC::Open3 qw( open3 );
open(local *CHILD1_STDIN, '<', '/dev/null')
or die $!;
pipe(local *CHILD2_STDIN, local *CHILD1_STDOUT)
or die $!;
my $child1_pid = open3(
'<&CHILD1_STDIN',
'>&CHILD1_STDOUT',
'>&STDERR',
'prog1', 'arg1', 'arg2',
);
my $child2_pid = open3(
'<&CHILD2_STDIN',
'>&STDOUT',
'>&STDERR',
'prog2', 'arg1', 'arg2',
);
my #pipe_status = map { waitpid($_, 0) } $child1_pid, $child2_pid;
IPC::Open3 is rather low level. IPC::Run3 and/or IPC::Run can possibly make this easier. [Update: Indeed, IPC::Run does].
If you want to check the status, don't put them all in the same system. Open a reading pipe to the first program to get its output then open another pipe to the other program.
The operating system returns an exit status only for the last program executed and if the OS doesn't return it, perl can't report it.
I don't know of any way to get at the exit code returned by earlier programs in a pipeline other than by running each individually and using temporary files instead of pipes.
What is the way to check the status of the first (or both) programs?
There is no such way, at least, not as you have constructed things. You may have to manage sub-processes yourself via fork(), exec() and waitpid() if you must know these things.
Here is roughly what is happening in your code fragment.
perl's system() spawns a shell, and perl *wait()*s for that subprocess to terminate.
The shell sets up a pipeline:
a subshell *exec()*s grep on the read-end of the pipe
a subshell fails to locate crontab1 anywhere in $PATH, and *exit()*s 127 (on my system, that is, where 127 is the shell indicating failure to find a program to run).
grep detects end-of-file on its input and, having matched nothing, *exit()*s 1.
The shell *exit()*s with the exit code of the last process in the pipeline, which, again, is 1.
perl detects the shell's exit code of 1, which is encoded in $? as 256.
(256 >> 8 == 1)

How can I test that a Perl program compiles from my test suite?

I'm building a regression system (not unit testing) for some Perl scripts.
A core component of the system is
`perl script.pl #params 1>stdoutfile 2>stderrfile`;
However, in the course of actually working on the scripts, they sometimes don't compile(Shock!). But perl itself will execute correctly. However, I don't know how to detect on stderr whether Perl failed to compile (and therefore wrote to stderr), or my script barfed on input (and therefore wrote to stderr).
How do I detect whether a program executed or not, without exhaustively finding Perl error messages and grepping the stderr file?
It might be easiest to do this in two steps:
system('$^X -c script.pl');
if ($? == 0) {
# it compiled, now let's see if it runs
system('$^X script.pl', #params, '1>stdoutfile', '2>stderrfile');
# check $?
}
else {
warn "script.pl didn't compile";
}
Note the use of $^X instead of perl. This is more flexible and robust. It ensures that you're running from the same installation instead of whatever interpreter shows up first in your path. The system call will inherit your environment (including PERL5LIB), so spawning a different version of perl could result in hard-to-diagnose compatibility errors.
When I want to check that a program compiles, I check that it compiles :)
Here's what I put into t/compile.t to run with the rest of my test suite. It stops all testing with the "bail out" if the script does not compile:
use Test::More tests => 1;
my $file = '...';
print "bail out! Script file is missing!" unless -e $file;
my $output = `$^X -c $file 2>&1`;
print "bail out! Script file does not compile!"
unless like( $output, qr/syntax OK$/, 'script compiles' );
Scripts are notoriously hard to test. You have to run them and then scrape their output. You can't unit test their guts... or can you?
#!/usr/bin/perl -w
# Only run if we're the file being executed by Perl
main() if $0 eq __FILE__;
sub main {
...your code here...
}
1;
Now you can load the script like any other library.
#!/usr/bin/perl -w
use Test::More;
require_ok("./script.pl");
You can even run and test main(). Test::Output is handy for capturing the output. You can say local #ARGV to control arguments or you can change main() to take #ARGV as an argument (recommended).
Then you can start splitting main() up into smaller routines which you can easily unit test.
Take a look at the $? variable.
From perldoc perlvar:
The status returned by the last pipe
close, backtick ("``") command,
successful call to wait() or
waitpid(), or from the system()
operator. This is just the 16-bit
status word returned by the
traditional Unix wait() system call
(or else is made up to look like it).
Thus, the exit value of the subprocess
is really ("$? >> 8"), and "$? & 127"
gives which signal, if any, the
process died from, and "$? & 128"
reports whether there was a core dump.
It sounds like you need IPC::Open3.

What's the difference between Perl's backticks, system, and exec?

Can someone please help me? In Perl, what is the difference between:
exec "command";
and
system("command");
and
print `command`;
Are there other ways to run shell commands too?
exec
executes a command and never returns.
It's like a return statement in a function.
If the command is not found exec returns false.
It never returns true, because if the command is found it never returns at all.
There is also no point in returning STDOUT, STDERR or exit status of the command.
You can find documentation about it in perlfunc,
because it is a function.
system
executes a command and your Perl script is continued after the command has finished.
The return value is the exit status of the command.
You can find documentation about it in perlfunc.
backticks
like system executes a command and your perl script is continued after the command has finished.
In contrary to system the return value is STDOUT of the command.
qx// is equivalent to backticks.
You can find documentation about it in perlop, because unlike system and execit is an operator.
Other ways
What is missing from the above is a way to execute a command asynchronously.
That means your perl script and your command run simultaneously.
This can be accomplished with open.
It allows you to read STDOUT/STDERR and write to STDIN of your command.
It is platform dependent though.
There are also several modules which can ease this tasks.
There is IPC::Open2 and IPC::Open3 and IPC::Run, as well as
Win32::Process::Create if you are on windows.
In general I use system, open, IPC::Open2, or IPC::Open3 depending on what I want to do. The qx// operator, while simple, is too constraining in its functionality to be very useful outside of quick hacks. I find open to much handier.
system: run a command and wait for it to return
Use system when you want to run a command, don't care about its output, and don't want the Perl script to do anything until the command finishes.
#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");
or
#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");
qx// or ``: run a command and capture its STDOUT
Use qx// when you want to run a command, capture what it writes to STDOUT, and don't want the Perl script to do anything until the command finishes.
#arguments are always processed by the shell
#in list context it returns the output as a list of lines
my #lines = qx/command arg1 arg2 arg3/;
#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;
exec: replace the current process with another process.
Use exec along with fork when you want to run a command, don't care about its output, and don't want to wait for it to return. system is really just
sub my_system {
die "could not fork\n" unless defined(my $pid = fork);
return waitpid $pid, 0 if $pid; #parent waits for child
exec #_; #replace child with new process
}
You may also want to read the waitpid and perlipc manuals.
open: run a process and create a pipe to its STDIN or STDERR
Use open when you want to write data to a process's STDIN or read data from a process's STDOUT (but not both at the same time).
#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
or die "could not open $filename: $!";
#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
or die "could not open $filename: $!";
IPC::Open2: run a process and create a pipe to both STDIN and STDOUT
Use IPC::Open2 when you need to read from and write to a process's STDIN and STDOUT.
use IPC::Open2;
open2 my $out, my $in, "/usr/bin/bc"
or die "could not run bc";
print $in "5+6\n";
my $answer = <$out>;
IPC::Open3: run a process and create a pipe to STDIN, STDOUT, and STDERR
use IPC::Open3 when you need to capture all three standard file handles of the process. I would write an example, but it works mostly the same way IPC::Open2 does, but with a slightly different order to the arguments and a third file handle.
Let me quote the manuals first:
perldoc exec():
The exec function executes a system command and never returns-- use system instead of exec if you want it to return
perldoc system():
Does exactly the same thing as exec LIST , except that a fork is done first, and the parent process waits for the child process to complete.
In contrast to exec and system, backticks don't give you the return value but the collected STDOUT.
perldoc `String`:
A string which is (possibly) interpolated and then executed as a system command with /bin/sh or its equivalent. Shell wildcards, pipes, and redirections will be honored. The collected standard output of the command is returned; standard error is unaffected.
Alternatives:
In more complex scenarios, where you want to fetch STDOUT, STDERR or the return code, you can use well known standard modules like IPC::Open2 and IPC::Open3.
Example:
use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
Finally, IPC::Run from the CPAN is also worth looking at…
What's the difference between Perl's backticks (`), system, and exec?
exec -> exec "command"; ,
system -> system("command"); and
backticks -> print `command`;
exec
exec executes a command and never resumes the Perl script. It's to a script like a return statement is to a function.
If the command is not found, exec returns false. It never returns true, because if the command is found, it never returns at all. There is also no point in returning STDOUT, STDERR or exit status of the command. You can find documentation about it in perlfunc, because it is a function.
E.g.:
#!/usr/bin/perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";
In above code, there are three print statements, but due to exec leaving the script, only the first print statement is executed. Also, the exec command output is not being assigned to any variable.
Here, only you're only getting the output of the first print statement and of executing the ls command on standard out.
system
system executes a command and your Perl script is resumed after the command has finished. The return value is the exit status of the command. You can find documentation about it in perlfunc.
E.g.:
#!/usr/bin/perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";
In above code, there are three print statements. As the script is resumed after the system command, all three print statements are executed.
Also, the result of running system is assigned to data2, but the assigned value is 0 (the exit code from ls).
Here, you're getting the output of the first print statement, then that of the ls command, followed by the outputs of the final two print statements on standard out.
backticks (`)
Like system, enclosing a command in backticks executes that command and your Perl script is resumed after the command has finished. In contrast to system, the return value is STDOUT of the command. qx// is equivalent to backticks. You can find documentation about it in perlop, because unlike system and exec, it is an operator.
E.g.:
#!/usr/bin/perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";
In above code, there are three print statements and all three are being executed. The output of ls is not going to standard out directly, but assigned to the variable data2 and then printed by the final print statement.
The difference between 'exec' and 'system' is that exec replaces your current program with 'command' and NEVER returns to your program. system, on the other hand, forks and runs 'command' and returns you the exit status of 'command' when it is done running. The back tick runs 'command' and then returns a string representing its standard out (whatever it would have printed to the screen)
You can also use popen to run shell commands and I think that there is a shell module - 'use shell' that gives you transparent access to typical shell commands.
Hope that clarifies it for you.