English 中文(简体)
How do I execute an external script while capturing both output and exit code in Perl?
原标题:

I m trying to check for an SVN tag existence from a Perl script. So I try calling svn info $url, read exit code and suppress standard output and standard error streams. However, I struggle to do this elegantly (there are probably better ways to ask SVN about a tag, but that s not the point here):

my $output = `svn info $url/tags/$tag`;

This suppresses the output while putting it into $output. Exit code is lost.

my $output = `svn info $url/tags/$tag 2>&1`;

This suppresses both STDERR and STDOUT and puts them both into $output. Exit code is again lost.

my $exitcode = system("svn", "info", "$url/tags/$tag");

This catches the exit code, but the actual output and error stream is visible to the user.

open( STDERR, q{>}, "/dev/null" );
open my $fh, q{>}, "/dev/null";
select($fh);
if (system("svn", "info", "$url/tags/$tag") != 0) {
   select(STDOUT);
   print ("Tag doesn t exist!");
   do_something_with_exit();
}
select(STDOUT);
print "Exit code: $exitcode";

This kills the STDOUT and STDERR and catches the exit code, but it s ugly because I d have to remeber to switch the STDOUT back to original.

So, is there any more elegant solution?

最佳回答

Try using $?.e.g.

my $output = `svn info $url/tags/$tag`;
my $extcode = $?>>8;
问题回答

What happens when you try it with IPC::System::Simple? That module handles most of the details of these sorts of problems:

 use IPC::System::Simple qw(capturex $EXITVAL);

 my $output = capturex( "some_command", @args );
 my $exit   = $EXITVAL;
 my $output = `svn info $url/tags/$tag 2>&1`;

This suppresses both STDERR and STDOUT and puts them both into $output. Exit code is again lost

Are you sure the exit code is lost? When I try this, I get the exit code in $?.

The module IPC::Run3 gives very fine-grained control over the input and output.

use IPC::Run3;
run3 @cmd, $in, $out, $err;

You can pass the same variable to $out and $err and it will do what you expect, combining both streams. The input is unnecessary, and so you can pass either undef ("inherit from parent process") or undef ("closed filehandle".)

IPC::Run3::run3() returns true or false depending on the exit code, and leaves the actual exit code of the child process in $? as per perlvar .

In your case you would run

use IPC::Run3

my @cmd = ( svn ,  info , "$url/tags/$tag");
my $out;
my $rv = run3(@cmd, undef, $out, $out);
if ($rv) {
    # process $out
}
else {
    die "error: $@";
}




相关问题
Why does my chdir to a filehandle not work in Perl?

When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...

How do I use GetOptions to get the default argument?

I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...

Object-Oriented Perl constructor syntax and named parameters

I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...

Where can I find object-oriented Perl tutorials? [closed]

A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...

热门标签