Abhishek
Abhishek

Reputation: 77

Redirecting STDOUT and STDERR to a file, except for standard output/error of system()

I am trying to run a Perl script in Linux and log all output to STDOUT and STDERR to a file using:

open (STDOUT, "| tee -i $transcript_file");
open (STDERR, "| tee -ai $transcript_file");

The script that uses this works roughly as follows:

  1. Create an environment for running a tool. Has many print, warn and possibly die statements.
  2. Run the tool (Currently using system command). This produces a lot of output which I want to appear on STDOUT, but not in the logfile (The tool creates its own logfile).
  3. Analyze the results, cleanup and exit. Has many print, warn and possibly die statements.

Everything works correctly except I would like to exclude the output of step 2 from the log. Is there a simple way to achieve this?

Thanks,

PS: This is my first question on stackoverflow. Please help me in asking questions correctly if I have not done so.

Upvotes: 3

Views: 691

Answers (2)

Hans Lub
Hans Lub

Reputation: 5678

I agree with Sobrique's advice to use a special function print_and_log. But if you really want to do it the way you set out to do, you can dup STDOUT and STDERR, redirect them to your log and then use open3 to run your tool with the dup'ed original standard output and error file descriptors

use  IPC::Open3;

# dup the old standard output and error 
open(OLDOUT, ">&STDOUT") or die "Can't dup STDOUT: $!\n";
open(OLDERR, ">&STDERR") or die "Can't dup STDERR: $!\n";

# reopen stdout and stderr
open (STDOUT, "|tee $transcript_file") or die "Can't reopen STDOUT: $!\n";
open (STDERR, ">&STDOUT")              or die "Can't reopen STDERR: $!\n";

# print statements now write to log
print "Logging important info: blah!\n";
print STDERR "OOPS!\n";

# run your command; output will go to original stdout
# this will die() instead of returning say -1, so use eval() to catch errors
my $pid = open3(">&OLDOUT", "<&STDIN", ">&OLDERR", $command); 

# wash those dishes....
waitpid( $pid, 0 );

Upvotes: 4

Sobrique
Sobrique

Reputation: 53478

Given you're reassigning STDIN and STDOUT then the short answer is no. You're capturing everything on STDOUT which includes your intermediate output.

You could probably close/reopen STDOUT for the bit where you didn't want it logging. But I'd suggest instead that you might want to consider what you're trying to accomplish - would a 'print_and_log' subroutine do what you're after?

Upvotes: 0

Related Questions