syker
syker

Reputation: 11272

How can I redirect the output of Perl's system() to a filehandle?

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.

Upvotes: 4

Views: 3694

Answers (4)

Ether
Ether

Reputation: 53966

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.

Upvotes: 3

cikkle
cikkle

Reputation: 458

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.

Upvotes: 3

mob
mob

Reputation: 118605

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}".

Upvotes: 1

codeholic
codeholic

Reputation: 5848

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";

Upvotes: 1

Related Questions