Re: Print to several logs
There are some good answers here so far, but I'd like to recommend a logging module like Log::Log4perl. If your script is more than a run-once throwaway, proper logging will almost certainly be of benefit. Metacpan: https://metacpan.org/module/Log::Log4perl FAQ: http://log4perl.sourceforge.net/releases/Log-Log4perl/docs/html/Log/Log4perl/FAQ.html Tutorial: http://www.perl.com/pub/2002/09/11/log4perl.html To log to two files: #!/usr/bin/perl use strict; use warnings; use Log::Log4perl qw(get_logger); # Normally this would be in a separate file my $log4perl_cfg = 'EOCFG'; # Two appenders in our logger tmplog1 tmplog2 log4perl.logger = DEBUG, tmplog1, tmplog2 log4perl.appender.tmplog1 = Log::Log4perl::Appender::File log4perl.appender.tmplog1.filename = /var/tmp/one.log log4perl.appender.tmplog1.layout = PatternLayout log4perl.appender.tmplog1.layout.ConversionPattern = %d %m%n log4perl.appender.tmplog2 = Log::Log4perl::Appender::File log4perl.appender.tmplog2.filename = /var/tmp/two.log log4perl.appender.tmplog2.layout = PatternLayout log4perl.appender.tmplog2.layout.ConversionPattern = %d %m%n EOCFG Log::Log4perl-init( \$log4perl_cfg ); my $logger = get_logger(); my $rsync = 'rsync'; $logger-debug('About to rsync'); ...; $logger-info(kdkdkdkd Output from: $rsync cmdflgs); exit 0; Using Log4perl allows you to change how you log very easily, with appenders for output to files, the screen, databases etc. all available. The configuration format is somewhat verbose, so I generally use the Template Toolkit to generate it for me. The example below solves your same problem, but for N files instead of two: #!/usr/bin/perl use strict; use warnings; use Log::Log4perl qw(get_logger); use Template; my $logging_cfg_template = 'EOCFG'; [% BLOCK appenders -%] [% FOR section IN sections %][% section.log_appender_name %][% , UNLESS loop.last %][% END %] [%- END %] [% BLOCK appender_sections %] [% FOR section IN sections %] log4perl.appender.[% section.log_appender_name %] = Log::Log4perl::Appender::File log4perl.appender.[% section.log_appender_name %].filename = [% section.log_file_name %] log4perl.appender.[% section.log_appender_name %].layout = PatternLayout log4perl.appender.[% section.log_appender_name %].layout.ConversionPattern = %d %m%n [% END %] [% END %] log4perl.logger = DEBUG, [% PROCESS appenders %] [% PROCESS appender_sections %] EOCFG my $template = { sections = [ { log_appender_name = 'tmplog1', log_file_name = '/var/log/one.log', }, { log_appender_name = 'tmplog2', log_file_name = '/var/log/two.log', }, { log_appender_name = 'tmplog3', log_file_name = '/var/log/three.log', }, ], }; my $tt = Template-new(); my $log4perl_cfg; $tt-process( \$logging_cfg_template, $template, \$log4perl_cfg ) || die 'Template error: ' . $tt-error(); # Comment or remove this line once you are happy with the generated config print CONFIG: $log4perl_cfg\n; Log::Log4perl-init( \$log4perl_cfg ); my $logger = get_logger('main'); my $rsync = 'rsync'; $logger-info(kdkdkdkd Output from: $rsync cmdflgs); Cheers, Michael On 08/28/2013 06:44 AM, Harry Putnam wrote: I happen to be scripting something that needs to have two logs written to and was sort of taken by how awkward this construction looked: (Simplified for discussion, from a longer script) my $rsync = 'rsync'; my $tmplog = 'one.log'; my $tmplog2 = 'two.log'; open(LOG,$tmplog)or die Can't open $tmplog : $!; open(LOG2,$tmplog2)or die Can't open $tmplog2: $!; print LOG kdkdkdkd Output from:\n$rsync cmdflgs; print LOG2 kdkdkdkd Output from:\n$rsync cmdflgs close(LOG); close(LOG2); Is there some smooth way to write to more than one log? I tried just adding the second one to the first print like this: print LOG LOG2 [...]; But that fails with an error: String found where operator expected at ./t1.pl line 109, near LOG2 kdkdkdkd Output from:\n$rsync cmdflgs (Do you need to predeclare LOG2?) syntax error at ./t1.pl line 109, near LOG2 kdkdkdkd Output from:\n$rsync cmdflgs Execution of ./t1.pl aborted due to compilation errors. -- Michael BraderSenior Software Engineer and Perl Person Our World Wide Web has a World Wide Network Technology/Softdev/DevOps Internode http://internode.on.net/ mbra...@internode.com.au iiNet http://iinet.net.au/ m.bra...@staff.iinet.net.au -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Print to several logs
Rob Dixon rob.di...@gmx.com writes: On 27/08/2013 23:06, John W. Krahn wrote: Harry Putnam wrote: [...] (Simplified for discussion, from a longer script) my $rsync = 'rsync'; my $tmplog = 'one.log'; my $tmplog2 = 'two.log'; open(LOG,$tmplog)or die Can't open $tmplog : $!; open(LOG2,$tmplog2)or die Can't open $tmplog2: $!; print LOG kdkdkdkd Output from:\n$rsync cmdflgs; print LOG2 kdkdkdkd Output from:\n$rsync cmdflgs close(LOG); close(LOG2); Is there some smooth way to write to more than one log? my %logs = ( 'one.log' = undef, 'two.log' = undef, ); for my $name ( keys %logs ) { open my $FH, '', $name or die Cannot open '$name' because: $!; $logs{ $name } = $FH; } for my $log_FH ( values %logs ) { print $log_FH kdkdkdkd Output from:\n$rsync cmdflgs; } Nice John Yes very nice... thank you John It compacts neatly to [...] snipped neatly compacted code Nicely compacted... thank you Rob. Thanks to all other posters.. lots of good input. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Print to several logs
On Wed, 28 Aug 2013 10:42:30 -0400 Harry Putnam rea...@newsguy.com wrote: Thanks to all other posters.. lots of good input. It seems to me that recording the same information is many places is a design flaw. If you have the same information in two or more places, it will get out of sync. Write the program that will detect and correct this, now, not later. -- Don't stop where the ink does. Shawn -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Make a sub routine return
I know the format and scripting are probably pretty backwards but I seem to recall it being important to have a `return' line in a function. The code below was a script by itself but now I need to turn it into a function inside a larger script... I've done something that sort of works but fails on a specific file name that looks like `.#somefile'. I'll show the code the way I've tried to turn it into a sub routine. So, I'd like comments both on how to write this more like a proper sub routine and any other why ideas. What the sub is supposed to do is plow thru a couple of directories and reset the proper owner and group after some other operations have changed them. Its called like this in a getops operation: if($opt_o ) { if (@ARGV) { usage(); print The \`-o' flag must be used by itself and\n, \`-o' flag requires user to be root .. exiting\n ; exit; } chOwnGrp(); exit; } sub chOwnGrp { use File::Find; my $buffer = '/merb'; my $module = '/usr/local/common/merc'; my $uname = $ENV{'LOGNAME'}; my $uid = '1000'; my $gid = '1050'; if ($uname =~ /root/) { print Would you like to set owner:group on BUFFER and MODULE?\n, If so, we will run chown -R $uid:$gid $buffer and\n, chown -R $uid:$gid $module\n, [y/n] ; my $answer = STDIN; if ($answer =~ /^y$/) { find( sub { chown $uid, $gid, $_ or warn could not chown '$_': $!; }, $buffer, $module ); } } else { print You must be root to run with this flag (-o) effectively.. exiting\n; print Not root - tripped at line: . __LINE__ . \n; exit; } } -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Print to several logs
Shawn H Corey shawnhco...@gmail.com writes: On Wed, 28 Aug 2013 10:42:30 -0400 Harry Putnam rea...@newsguy.com wrote: Thanks to all other posters.. lots of good input. It seems to me that recording the same information is many places is a design flaw. If you have the same information in two or more places, it will get out of sync. Write the program that will detect and correct this, now, not later. Good thinking thanks. It might not really apply here though. I'm no kind of data manager... just a homeboy hillbilly. What I had in mind is writing to a single log file that is dated on the file name for each run of the program. That file will sooner or later be deleted by another part of the script that will try to leave 5 of the most recent logs. I was going to just cat the fresh log, onto an accumlative log after each run so the info would stick around for a while longer in case some kind of problem came up requiring research into previous runs older than the 5 dated logs. So the info is really only duplicated for a few weeks. That accumulative file might grow quite a bit. I find it handier to look thru a few dated logs that are much smaller ... but if it comes down to it and the dated logs don't go back far enough then I can find it in the accumulative log. That too, will get trimmed back eventually, That sounds quite a bit like what cron could do with this hmm. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Print to several logs
On Wed, 28 Aug 2013 12:34:40 -0400 Harry Putnam rea...@newsguy.com wrote: That sounds quite a bit like what cron could do with this hmm. Or use a hard link to preserve the file. -- Don't stop where the ink does. Shawn -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Print to several logs
Rob Dixon wrote: On 27/08/2013 23:06, John W. Krahn wrote: my %logs = ( 'one.log' = undef, 'two.log' = undef, ); for my $name ( keys %logs ) { open my $FH, '', $name or die Cannot open '$name' because: $!; $logs{ $name } = $FH; } for my $log_FH ( values %logs ) { print $log_FH kdkdkdkd Output from:\n$rsync cmdflgs; } Nice John It compacts neatly to use strict; use warnings; use autodie; my $rsync = 'rsync'; my $tmplog = 'one.log'; my $tmplog2 = 'two.log'; my %logs = map { open my $FH, '', $_; What if open fails?! ($_ = $FH); } $tmplog, $tmplog2; Or a bit more compact: my %logs = map { open my $FH, '', $_ or die Cannot open '$name' because: $!; ( $_ = $FH ); } my ( $tmplog, $tmplog2 ) = qw( one.log two.log ); John -- Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction. -- Albert Einstein -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Make a sub routine return
On 28/08/2013 16:48, Harry Putnam wrote: The code below was a script by itself but now I need to turn it into a function inside a larger script... I've done something that sort of works but fails on a specific file name that looks like `.#somefile'. What does fails mean? Does it crash?, produce an error message?, seem to work but have no effect?... Rob -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Print to several logs
On 28/08/2013 19:06, John W. Krahn wrote: Rob Dixon wrote: use strict; use warnings; use autodie; my $rsync = 'rsync'; my $tmplog = 'one.log'; my $tmplog2 = 'two.log'; my %logs = map { open my $FH, '', $_; What if open fails?! I have `use autodie`. Rob -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: Print to several logs
On Wed, 28 Aug 2013 12:34:40 -0400 Harry Putnam rea...@newsguy.com wrote: Good thinking thanks. It might not really apply here though. I'm no kind of data manager... just a homeboy hillbilly. What I had in mind is writing to a single log file that is dated on the file name for each run of the program. That file will sooner or later be deleted by another part of the script that will try to leave 5 of the most recent logs. Try this. It will keep rotating log files for the day-of-month, month, and year. # -- # Name: start_logging # Usage: $log_fh = start_logging( $log_file ); #Purpose: To open log file and set a day-of-month, month, and year # file that tracks it. # Parameters: $log_file -- full path to log file #Returns: $log_fh -- file handle to open log file # use Carp; use English qw( -no_match_vars ); # Avoids regex performance penalty use File::Basename; use POSIX; sub start_logging { my $log_file = shift @_; my @now = localtime; open my $log_fh, '', $log_file or croak could not open $log_file because: $OS_ERROR\n; my $dir = dirname( $log_file ); # link to day-of-month log file my $day_file = strftime $dir/day_%d.log, @now; unlink $day_file; # ignore errors link $log_file, $day_file or carp could not link to day-of-month file, $day_file because: $OS_ERROR\n; # link to month log file my $month_file = strftime $dir/mo_%m.log, @now; unlink $month_file; # ignore errors link $log_file, $month_file or carp could not link to day-of-month file, $month_file because: $OS_ERROR\n; # link to year log file my $year_file = strftime $dir/yr_%Y.log, @now; unlink $year_file; # ignore errors link $log_file, $year_file or carp could not link to day-of-month file, $year_file because: $OS_ERROR\n; return $log_fh; } -- Don't stop where the ink does. Shawn -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/