G'day GreenLantern,

I see ++choroba has provided a solution to your syntax error. You have other problems with your code which Perl will tell you about, if you ask it to, by including the strict and warnings pragmata.

Consider this fairly innocuous looking piece of code.

$ perl -E 'open my $fh, ">", "xxx"; close $fb; open my $fh, ">", "yyy" +' $

As you can see, it runs without any apparent problems. However, it does in fact contain one of the problems in your posted code. I've introduced another problem which is easy to make: I typed one key adjacent to the one I wanted (i.e. a fairly basic typo we all can make from time to time). Now look what happens if I'd asked Perl to tell me about problems.

$ perl -E 'use strict; use warnings; open my $fh, ">", "xxx"; close $f +b; open my $fh, ">", "yyy"' "my" variable $fh masks earlier declaration in same scope at -e line 1 +. Global symbol "$fb" requires explicit package name (did you forget to +declare "my $fb"?) at -e line 1. Execution of -e aborted due to compilation errors. ken@ganymede: ~/tmp $

The first problem it reports is the same as you have in your code (except yours is $FH, not $fh). The second one is the typo I introduced: 'b' is adjacent to 'h' on the keyboard; the shape of those two characters is very similar, making the problem easy to overlook.

The typo is easy to fix: s/b/h/. The other problem could be overcome by:

Here's one possible fix for both those problems:

$ perl -E 'use strict; use warnings; { open my $fh, ">", "xxx"; } open + my $fh, ">", "yyy"' $

Note that I could have fixed the typo but, as Perl closes filehandles when they go out of scope, I didn't need the close statement, and that problem just disappeared all by itself.

Make a point of adding these lines to the start of all your scripts:

use strict; use warnings;

It's good that you're checking for I/O problems; however, you're providing no information about the problem. In two places you have:

die "CANNOT OPEN LOG";

That provides no feedback about why open failed or which log file had the problem. Perl provides $! which holds the reason for the failure; you already know the filename and need to provide that youself. Those die statements would've been better written something like:

die "CANNOT OPEN LOG '$logfilename': $!";

Hand-crafting your own die messages is both tedious and error-prone. This is another task you can just let Perl do for you with the autodie pragma. When you do need custom error handling, such as in your second open statement, you should take a copy of $! as early as possible (it could be changed by another statement in your custom handler), and turn off autodie functionality (i.e. with no autodie 'open';) in the smallest scope possible (e.g. add use autodie 'open'; right after the open statement).

I notice you're selecting different filehandles before each print statement. Althougn print does use the currently selected filehande by default, you can specify the filehandle as part of the print statement. As STDOUT is the default filehandle, instead of

select $fh; print "..."; select STDERR; print "..."; select STDOUT; print "...";

you can just write

print $fh "..."; print STDERR "..."; print "...";

Going back to your various, previous problems with custom error handling, I think there's a better way to do this which makes your intent much clearer (and, therefore, subsequent reading and maintenance much easier). Consider something along these lines:

my $open_ok = open my $fh, $mode, $filename; if (not $open_ok) { # custom error handling here }

One final point about you're open statements. You typically want to append to log files, so use '>>' for the MODE; if you use '>' , you'll delete all previous log data.

Putting all that together, your code above could be written like this (untested).

#!/tps/bin/perl use strict; use warnings; use autodie; { my $logfilename = './test.log'; open my $fh, '>>', $logfilename; print $fh "..."; print "..."; } { my $logfilename = './test2.log'; no autodie 'open'; my $open_ok = open my $fh, '>>', $logfilename; use autodie 'open'; if (not $open_ok) { my $os_error = $!; print "Can't open '$logfilename': $os_error\n"; die "Can't open '$logfilename': $os_error"; } print $fh "..."; print "..."; }

Update (fix): s/filehandle/filename/ in (what was) my $open_ok = open my $fh, $mode, $filehandle;

— Ken


In reply to Re^3: Multiple actions triggered by failure to open a file by kcott
in thread Multiple actions triggered by failure to open a file by GreenLantern

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.