0

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!

6 Answers 6

3

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

1 Comment

thanks, for your input, Michele. It's not what I actually want, but it seems that it's impossible to do what I need.
1

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

2 Comments

Everything is fine but there is no output in the console, unfortunately.
No, there is not output to the console. As I said, you can cat (in a shell) or print the output file to the console. You might do that if/only the output file is not empty (size>0).
1

You can try to following by redirect stderr into stdout.

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

3 Comments

Yeah, I tried it, but I also wanna output from java in the console. That the issue I can't solve.
Use tee - my $retvar = system("java -jar prog.jar |tee file.txt 2>&1 > output.log ");
tee prevents me from getting a return code which helps me to know how java code did his job.
0

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

3 Comments

No, that's not what I looking for. I need to make a redirection only for java program output. And also the conditions are so that I can't add anything to the perl script execution statement.
Well, then you probably could use "open3" function from IPC::Open3 module. It should allow you to open separate handles for STDIN, STDOUT and STDERR, and you should be able to read your Java program output from STDOUT and STDERR handles line by line, and writing it into a file if you need to do so.
And there is an example in the documentation on CPAN on how to capture the proccess exit code with open3.
0

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'} );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.