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

I am pretty new to programming. I do my best to live by the docs, but sometimes strange things get me. I have tried several variations of this code. It logs it correctly (as I expect it to), but it also sets $! to 'Inappropriate I/O control operation.'

Oh, teachers of perl wisdom, where have I failed my poor program?

logger('I would like to log an arbitrary string, please.');
sub logger{ my $entry = shift(@_); my $logpath = 'C:\\Logs\\MailServer\\'; use vars qw($sec $min $hour $mday $mon $year $wday $yday $isdst); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime( +time); my $datestamp = (1900+$year).'_'.(1+$mon).'_'.$mday; my $timestamp = '~<'.$hour.':'.$min.':'.$sec.'>~ '; my $logname = $logpath.$datestamp.'.log'; if ($entry){ open my $LOG, ">>", "$logname" or die $!; print $LOG "$timestamp$entry\n"; say $timestamp.$entry; close($LOG); } }

Replies are listed 'Best First'.
Re: Lammentful logs fouled by failing filehandling
by JavaFan (Canon) on Apr 30, 2012 at 22:15 UTC
    It logs it correctly (as I expect it to), but it also sets $! to 'Inappropriate I/O control operation.'
    Yeah, and?

    $! is defined to contain only a meaningful value right after a failed system call (it links to errno, which has the same behaviour). Any system call is free to do whatever it wants with errno/$! if the call succeeds.

    Since your code succeeds, the value of $! is meaningless.

Re: Lammentful logs fouled by failing filehandling
by eyepopslikeamosquito (Archbishop) on May 01, 2012 at 10:09 UTC

    Kudos on the amusing node title. And your coding style did not cause me to pull a face. That said, I made some minor "improvements" based on my personal taste:

    sub logger { my $entry = shift; my $logpath = 'C:\\Logs\\MailServer\\'; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localti +me; my $datestamp = sprintf '%04d_%02d_%02d', 1900+$year, 1+$mon, $mda +y; my $timestamp = sprintf '~<%02d:%02d:%02d>~', $hour, $min, $sec; my $logname = $logpath . $datestamp . '.log'; my $logline = $timestamp . $entry; if (defined $entry) { open my $LOG, '>>', $logname or die "open: '$logname': $!"; say $LOG $logline or die "say: '$logname': $!"; say $logline; close $LOG; } }
    Note the minor differences and make up your own mind. In particular, note the use of sprintf so that the dates and times are formatted more uniformly and thus sort correctly.