mr.nothing
mr.nothing

Reputation: 5399

Perl: redirect output both to file and console, keeping return code

I've a problem. In my Perl script I execute a java program which print both to stdout and stderr streams. Could you please give me a peace of advice of how I can redirect stderr to file only and stdout to the same file and to the console. tee is not applicable here because I also need a return code of the java program. Any ideas?

Thanks in advance!

Upvotes: 0

Views: 3084

Answers (6)

Ven'Tatsu
Ven'Tatsu

Reputation: 3635

Bash includes an option pipefail to have pipelines return the rightmost failure code instead of the rightmost exit code.

You might be able to take something like this to run your command in bash with pipefail set.

my $ret = system( q{bash -c 'set -o pipefail; java command 2>>~/test_file | tee -a ~/test_file'} );

Upvotes: 0

Caldrin
Caldrin

Reputation: 101

Use IPC::Open3 to call the java program. Use IO::Select to read from the file handles. Do the writing yourself.

IPC::Open3 does a fork() and exec() for you so you get the return value using waitpid.

Upvotes: 3

chunk
chunk

Reputation: 19

You can try to following by redirect stderr into stdout.

my $retvar = system("java -jar prog.jar 2>&1  > output.log ");

Upvotes: 1

JRFerguson
JRFerguson

Reputation: 7526

Consider doing it thusly:

 perl -le 'qx(java -jar prog.jar>output.log 2>&1);$rc=$?;print "rc=",$rc<0 ? -1:$rc>>8'

This will redirect both STDOUT and STDERR into your file and capture and print the return code. Examine (or cat) the output file to the console as necessary. Look at qx and system for more insight.

UPDATE: Another way is something like this (i.e. secondarily writing the output file):

my $msg=qx(java -jar prog.jar 2>&1);
my $rc=$? < 0 ? -1 : $? >>8, "\n";
print  $msg, "rc=$rc\n";
open my $fh, '>', 'output.log' or die "$!\n";
print  {$fh} $msg, "rc=$rc\n";

Upvotes: 1

arthas
arthas

Reputation: 149

You can't do that directly from the shell (without tee).

Maybe you could redirect to a file, then open that file from inside the perl script and print to the console. Something like:

use Path::Class; # Handy module, but you can do without

my $retvar = system("java -jar prog.jar >stdout.log 2>stderr.log ");

my $output = file('.', 'stdout.log')->slurp();
print $output; # or print STDERR $output;

Hope this helps a bit. It still keeps the file separated, which is maybe not what you wanted.

Michele.

Upvotes: 1

eyevan
eyevan

Reputation: 1473

If you're under *nix you should look up "tee" command.

You should probably do something like:

perl script.pl 2>stderr.out | tee stdout.out

Upvotes: 0

Related Questions