Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Print STDOUT and STDERR to file and to console

by Noame (Beadle)
on Jul 30, 2009 at 19:22 UTC ( [id://784712]=perlquestion: print w/replies, xml ) Need Help??

Noame has asked for the wisdom of the Perl Monks concerning the following question:

I Need Something like the following:
open(LOG, "> $LOG_FILE") || die "Can't redirect stdout"; #open(STDERR, ">&STDOUT") || die "Can't dup stdout"; open (CMD, " ls |"); while (<CMD>) { lprint ($_) } close(CMD); sub lprint () { my ($line) = @_; print LOG $line; # print STDERR $line; # print STDERR $_; print $line; }

The problem with the example above is that I can’t catch error messages (STDERR) and print them to log file and the console.
Any Idea how to handle the STDERR as well?

Thanks.

Replies are listed 'Best First'.
Re: Print STDOUT and STDERR to file and to console
by kennethk (Abbot) on Jul 30, 2009 at 19:43 UTC
Re: Print STDOUT and STDERR to file and to console
by Marshall (Canon) on Jul 30, 2009 at 21:55 UTC
    tee for output re-direction is a standard Unix tool, but doesn't normally exist on Windows. Very complex is both input and output teeing!

    But the basic version to split output is not hard:

    #!usr/bin/perl -w use strict; $|=1; #turn autoflush on #tee.pl sub usage () { print "TEE USAGE:\n". " program | tee outfile\n". " sends stdout from program to outfile\n"; exit; } my $filename = shift @ARGV; usage unless $filename; open (OUTFILE, ">", "$filename") or (die "Can't open OUTFILE: $!"); while (<>) { print; print OUTFILE; }
    Yep, that's pretty much it. Open for append if you like.
Re: Print STDOUT and STDERR to file and to console
by ikegami (Patriarch) on Jul 30, 2009 at 19:34 UTC
    Won't the code we post be imported into your script?
      Yes
        I guess you can't use our answers then, but here you go anyway.
        BEGIN { package IO::Tee; require 5.004; use strict; use Carp; use Symbol; use IO::Handle; use IO::File; use vars qw($VERSION @ISA); $VERSION = '0.64'; @ISA = 'IO::Handle'; # Constructor -- bless array reference into our class sub new { my $class = shift; my $self = gensym; @{*$self} = map { ! ref($_) ? IO::File->new($_) : ref($_) eq 'ARRAY' ? IO::File->new(@$_) : ref($_) eq 'GLOB' ? bless $_, 'IO::Handle' : $_ or return undef } @_; bless $self, $class; tie *$self, $class, $self; return $self; } # Return a list of all associated handles sub handles { @{*{$_[0]}}; } # Proxy routines for various IO::Handle and IO::File operations sub _method_return_success { my $method = (caller(1))[3]; $method =~ s/.*:://; my $self = shift; my $ret = 1; foreach my $fh (@{*$self}) { undef $ret unless $fh->$method(@_ +) } return $ret; } sub close { _method_return_success(@_) } sub truncate { _method_return_success(@_) } sub write { _method_return_success(@_) } sub syswrite { _method_return_success(@_) } sub format_write { _method_return_success(@_) } sub fcntl { _method_return_success(@_) } sub ioctl { _method_return_success(@_) } sub flush { _method_return_success(@_) } sub clearerr { _method_return_success(@_) } sub seek { _method_return_success(@_) } sub formline { my $self = shift; my $picture = shift; local($^A) = $^A; local($\) = ""; formline($picture, @_); my $ret = 1; foreach my $fh (@{*$self}) { undef $ret unless print $fh $^A } return $ret; } sub _state_modify { my $method = (caller(1))[3]; $method =~ s/.*:://; croak "$method values cannot be retrieved collectively" if @_ +<= 1; my $self = shift; if (ref $self) { foreach my $fh (@{*$self}) { $fh->$method(@_) } } else { IO::Handle->$method(@_); } # Note that we do not return any "previous value" here } sub autoflush { _state_modify(@_) } sub output_field_separator { _state_modify(@_) } sub output_record_separator { _state_modify(@_) } sub format_page_number { _state_modify(@_) } sub format_lines_per_page { _state_modify(@_) } sub format_lines_left { _state_modify(@_) } sub format_name { _state_modify(@_) } sub format_top_name { _state_modify(@_) } sub format_line_break_characters { _state_modify(@_) } sub format_formfeed { _state_modify(@_) } sub input_record_separator { my $self = shift; my $ret = (ref $self ? ${*$self}[0] : 'IO::Handle') ->input_record_separator(@_); $ret; # This works around an apparent bug in Perl 5.004_04 } sub input_line_number { my $self = shift; my $ret = ${*$self}[0]->input_line_number(@_); $ret; # This works around an apparent bug in Perl 5.004_04 } # File handle tying interface sub TIEHANDLE { my ($class, $self) = @_; return bless *$self{ARRAY}, $class; } sub PRINT { my $self = shift; my $ret = 1; foreach my $fh (@$self) { undef $ret unless print $fh @_ } return $ret; } sub PRINTF { my $self = shift; my $fmt = shift; my $ret = 1; foreach my $fh (@$self) { undef $ret unless printf $fh $fmt, @ +_ } return $ret; } sub _multiplex_input { my ($self, $input) = @_; my $ret = 1; if (length $input) { for (my $i = 1; $i < @$self; ++$i) { undef $ret unless print {$self->[$i]} $input; } } $ret; } sub READ { my $self = shift; my $bytes = $self->[0]->read(@_); $bytes and $self->_multiplex_input(substr($_[0], $_[2], $bytes +)); $bytes; } sub READLINE { my $self = shift; my $infh = $self->[0]; if (wantarray) { my @data; my $data; while (defined($data = <$infh>) and length($data)) { push @data, $data; $self->_multiplex_input($data); } @data; } else { my $data = <$infh>; defined $data and $self->_multiplex_input($data); $data; } } sub GETC { my $self = shift; my $data = getc($self->[0]); defined $data and $self->_multiplex_input($data); $data; } sub sysread { my $self = shift; my $bytes = ${*$self}[0]->sysread(@_); $bytes and (\@{*$self})-> _multiplex_input(substr($_[0], $_[2] || 0, $bytes)); $bytes; } sub EOF { my $self = shift; return $self->[0]->eof; } BEGIN { $INC{"IO/Tee.pm"} = __FILE__; } =head1 NAME IO::Tee - Multiplex output to multiple output handles =head1 SYNOPSIS use IO::Tee; $tee = IO::Tee->new($handle1, $handle2); print $tee "foo", "bar"; my $input = <$tee>; =head1 DESCRIPTION C<IO::Tee> objects can be used to multiplex input and output in two different ways. The first way is to multiplex output to zero or more output handles. The C<IO::Tee> constructor, given a list of output handles, returns a tied handle that can be written to. When written to (using print or printf), the C<IO::Tee> object multiplexes the output to the list of handles originally passed to the constructor. As a shortcut, you can also directly pass a string or an array reference to the constructor, in which case C<IO::File::new> is called for you with the specified argument or arguments. The second way is to multiplex input from one input handle to zero or more output handles as it is being read. The C<IO::Tee> constructor, given an input handle followed by a list of output handles, returns a tied handle that can be read from as well as written to. When written to, the C<IO::Tee> object multiplexes the output to all handles passed to the constructor, as described in the previous paragraph. When read from, the C<IO::Tee> object reads from the input handle given as the first argument to the C<IO::Tee> constructor, then writes any data read to the output handles given as the remaining arguments to the constructor. The C<IO::Tee> class supports certain C<IO::Handle> and C<IO::File> methods related to input and output. In particular, the following methods will iterate themselves over all handles associated with the C<IO::Tee> object, and return TRUE indicating success if and only if all associated handles returned TRUE indicating success: =over 4 =item close =item truncate =item write =item syswrite =item format_write =item formline =item fcntl =item ioctl =item flush =item clearerr =item seek =back The following methods perform input multiplexing as described above: =over 4 =item read =item sysread =item readline =item getc =item gets =item eof =item getline =item getlines =back The following methods can be used to set (but not retrieve) the current values of output-related state variables on all associated handles: =over 4 =item autoflush =item output_field_separator =item output_record_separator =item format_page_number =item format_lines_per_page =item format_lines_left =item format_name =item format_top_name =item format_line_break_characters =item format_formfeed =back The following methods are directly passed on to the input handle given as the first argument to the C<IO::Tee> constructor: =over 4 =item input_record_separator =item input_line_number =back Note that the return value of input multiplexing methods (such as C<print>) is always the return value of the input action, not the return value of subsequent output actions. In particular, no error is indicated by the return value if the input action itself succeeds but subsequent output multiplexing fails. =head1 EXAMPLE use IO::Tee; use IO::File; my $tee = new IO::Tee(\*STDOUT, new IO::File(">tt1.out"), ">tt2.out"); print join(' ', $tee->handles), "\n"; for (1..10) { print $tee $_, "\n" } for (1..10) { $tee->print($_, "\n") } $tee->flush; $tee = new IO::Tee('</etc/passwd', \*STDOUT); my @lines = <$tee>; print scalar(@lines); =head1 AUTHOR Chung-chieh Shan, ken@digitas.harvard.edu =head1 COPYRIGHT Copyright (c) 1998-2001 Chung-chieh Shan. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L<perlfunc>, L<IO::Handle>, L<IO::File>. =cut

        Place that in your script before any use IO::Tee; statements (although such statements are optional).

        Don't forget to heed the license: Copyright (c) 1998-2001 Chung-chieh Shan. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

Re: Print STDOUT and STDERR to file and to console
by ikegami (Patriarch) on Jul 30, 2009 at 22:30 UTC
    "STDOUT and STDIN" or "STDOUT and STDERR"? You used both in different places.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://784712]
Approved by kennethk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2024-04-20 03:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found