views:

415

answers:

4

With the open command in Perl, you can use a filehandle. However I have trouble getting back the exit code with the open command in Perl.

With the system command in Perl, I can get back the exit code of the program I'm running. However I want to just redirect the STDOUT to some filehandle (no stderr).

My stdout is going to be a line-by-line output of key-value pairs that I want to insert into a mao in perl. That is why I want to redirect only my stdout from my Java program in perl. Is that possible?

Note: If I get errors, the errors get printed to stderr. One possibility is to check if anything gets printed to stderr so that I can quite the Perl script.

A: 

This is one of the ways to do it.

open my $fh, '>', $file;
defined(my $pid = fork) or die "fork: $!";
if (!$pid) {
    open STDOUT, '>&', $fh;
    exec($command, @args);
}
waitpid $pid, 0;
print $? == 0 ? "ok\n" : "nok\n";
codeholic
A: 

Use open in -| mode. When you close the filehandle, the exit status will be in $?.

open my $fh, '-|', "$command";  # older version:  open my $fh, "$command |";
my @command_output = <$fh>;
close $fh;
my $command_status = $?;

From perldoc -f close

If the file handle came from a piped open, "close" will additionally return false if one of the other system calls involved fails, or if the program exits with non-zero status. (If the only problem was that the program exited non-zero, $! will be set to 0.) Closing a pipe also waits for the process executing on the pipe to complete, in case you want to look at the output of the pipe afterwards, and implicitly puts the exit status value of that command into $? and "${^CHILD_ERROR_NATIVE}".

mobrule
Strictly speaking, the question was on how to redirect a command's output to an already opened filehandle, not how to capture it.
codeholic
@codeholic - strictly speaking, the second sentence of the OP expresses interest in getting the exit code back from an `open` statement. The OP recognized there are many ways to accomplish this task and did a good job of avoiding a 'How do I use X to accomplish Y?' type of question.
mobrule
Strictly speaking, there's no interest in `open` in the second sentence. The exit code just should have been got, and it doesn't matter how.
codeholic
+2  A: 

You may want to check out IPC::System::Simple -- it gives you many options for executing external commands, capturing its output and return value, and optionally dying if a bad result is returned.

Ether
+1  A: 

Canonically, if you're trying to get at the text output of a forked process, my understanding is that's what the backticks are for. If you need the exit status as well, you can check it with the $? special variable afterward, e.g.:

open my $fh, '>', "output.txt" or die $!;
print {$fh} `echo "Hello!"`;
print "Return code: $?\n";

Output to STDERR from the command in backticks will not be captured, but will instead be written directly to STDERR in the Perl program it's called from.

cikkle