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

I have some Perl code, that has been running for a few years, and now, suddenly it will no longer function properly. I have put it thru the Perl Debugger and everything works fine - code wise. The issue is that it will no longer disply on the page. I have looked up __END__ and found that most every page says it is a "end of file" type of command, and all remaining lines will be skipped. I am not sure if I believe that or not, as this worked fine for years and nothing has changed on the code end. Here is the code:
#!perl use strict; use warnings; use File::Copy; print "Content-type: text/html\n\n"; my @servers = (); for my $i (1..9) { push @servers, "serverpd0${i}"; } push @servers, qw (serverpd15); for my $server (@servers) { my $audit_file = "\\\\$server\\c\$\\program files\\maintenance\\au +dit.txt"; if (-e $audit_file) { copy($audit_file, "tmp\\$server.log") or die $!; } } print "<pre>"; print system("cat.exe tmp\\*.log | c:\\wbin\\sort.exe -k 3 -r"); print "</pre>"; exit; __END__ print qq { <html> <body style="margin:0;padding:1px;"> }; print "<table width='100%' cellpadding='1' border='1' style='border:1p +x black solid;border-collapse:collapse;font-family:tahoma;font-size:1 +1px;'>"; print qq{ <tr style="background:black;color:white;font-weight:900;"> <td>Timestamp</td> <td>Username</td> <td>Where From</td> <td>Record Type</td> <td>Record Data</td> <td>Field Name</td> <td>Action</td> <td colspan="13">Data</td> </tr> }; for my $timestamp (reverse sort keys %logs) { for my $entry (@{$logs{$timestamp}}) { print "<tr><td>"; my @temp = split("\t", $entry); splice @temp, 1, 3; unshift @temp, $timestamp; print join("</td><td>", @temp); print "</td></tr>"; } } print qq{ </table> </body> </html> };
Can someone please tell me what the __END__ really does? if it is ignoring the remaining lines, why did it work for 2 years like this? What would be a better way to have this displayed on a IE page? Any assistance would be great!

Replies are listed 'Best First'.
Re: Does __END__ really mean ignore rest of lines?
by ELISHEVA (Prior) on Jan 17, 2011 at 18:46 UTC

    It depends on what you mean by "ignore". __END__ tells the Perl interpreter not to interpret and execute anything after it. If that is what you mean by "ignore", then yes, it really does mean "ignore". Under certain circumstances, those lines can still be read in as data, via the DATA file handle as Anonymous Monk said above, but they will never be executed by typing perl "myscript.pl on the command line, nor by using do "myscript.pl" in a Perl script.

    Has your surrounding environment changed? This script is very dependent on the network it is part of. For it to work, you need the following:

    • Machines named serverpd01, serverpd02....serverpd09 and serverpd15. Do those machines exist? Has anyone renamed any servers recently?

    • On each of those machines you need to have log files with the name C:\Program Files\Maintenance\audit.txt. Do those files exist on serverpd01 etc?

    • The commands cat.exe and c:\\wbin\\sort.exe must exist on the machine where this script is running. Do they?

    • C:\wbin\sort.exe uses a fully qualified path, but cat.exe does not. What is the setting of the PATH environment variable inside the script? (add the line print STDERR "PATH=<", $ENV{PATH}, ">\n" to see). Is cat.exe on that path? If not, the script will fail.

    I doubt the code below the __END__ has much to do with your problem. It looks to me like someone was trying to quickly comment out an old attempt to format the log file information. The current script uses a different technique: it runs a shell command and dumps the output between <pre> tags. (last three lines before exit)

    As this script only prints out a content type declaration and a <pre>....</pre>, I strongly suspect that you will need to hunt down another script that runs this code and takes the output and inserts it into an actual HTML page.

    There is a small possibility that some other script is populating %log, reading the stuff after __END__ as data, eval'ing it, and inserting the contents into an HTML page. But again, this means that the real work, and possibly your problems, are due to changes in this other script or the environment it relies on.

      Thank you for your suggestions. I have verified that the machines are all named correctly and do exist. The log files are in the correct path on each of the machines, and the Unix commands are in the correct area of the machine. My PATH also has the proper locations listed in it.

      I will try to determine if there is some other pgm calling this one. I have not done that as of yet. Thank you again for your time and the suggestions</>

      The __END__ special value denotes the logical "end of file" for your program to the Perl interpreter. Everything that follows this special constant is treated as data and may be read via the filehandle.

Re: Does __END__ really mean ignore rest of lines?
by toolic (Bishop) on Jan 17, 2011 at 18:07 UTC
    Does your problem go away if you delete everything after __END__?

    Update: unrelated, but normally, you can replace for/push with map. Change:

    my @servers = (); for my $i (1..9) { push @servers, "serverpd0${i}"; }
    to:
    my @servers = map { "serverpd0$_" } 1 .. 9;
Re: Does __END__ really mean ignore rest of lines?
by Anonyrnous Monk (Hermit) on Jan 17, 2011 at 18:06 UTC

    __END__ is essentially the same as __DATA__ (when used in the main namespace). Anything after it is considered arbitrary data that can be read via the special file handle DATA-

    As to whether or why the script worked for two years but no longer does now, I don't know. It explicitly exits anyway before getting to the __END__ section...  Presumably, at the time it worked, you've been running some other incarnation of the script.

Re: Does __END__ really mean ignore rest of lines?
by JavaFan (Canon) on Jan 17, 2011 at 18:13 UTC
    Wait. Are you claiming that for years, Perl executed the code following the __END__? Do you really think in 2009 and 2010 __END__ was a token that does absolutely nothing (but in 2011 got its current meaning)? Note that there isn't even a semi-colon separating __END__ from print.

      I am claiming that for the past 2 plus years this has been a IE page that users have been able to click on (via a link) and it opens up an IE page that has the data formatted with all the HTML code AFTER the __END__ statement.

      I am trying to determine why suddenly it will no longer display the data in an IE page, but only shows a blank white page.

      I spent time online trying to determine what __END__ did, and became confused by what I learned. This is why I posted this question. I am not claiming anything, simply stating how it has worked. I am new to Perl and only have been working with it for a few months (only when the code 'breaks').

      How was the formatting code executed??? I have no clue how it was done. I do know that the page was displayed with all the HTML formatting after the __END__ statment and now it is no longer displayed. The code above the __END__ runs fine through the Perl Debugger and also from Command Line, but of course it is not presented in a nice orderly formatted format!

      Thank you anyway

        Your diagnosis is wrong. There's no way the code after the __END__ was being run. Furthermore, it wouldn't produce anything useful if you were to run it because it takes its information from variable %logs which doesn't exist.

        The question you should be asking is not "How was this code run?" (it wasn't), but rather "Which code was being run?". You are not looking at the right (version of the) file.

Re: Does __END__ really mean ignore rest of lines?
by CountZero (Bishop) on Jan 18, 2011 at 08:00 UTC
    The issue is that it will no longer disply on the page.
    That is a bit meagre as a description of this error.

    Does it print anything at all? Perhaps some error message?

    Is the script run through a web-server (the inclusion of some HTML code seems to suggest this)? If so, does the script run as expected when called from the command line?

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      This will only produce a blank white page. No error, no nothing. I guess this would be what to expect from what I have undersood so far. The script will run fine from the command line, but of course it is not formatted, and is way too long for the user to be able to see the data in a command window.

      I will be looking at a few other suggestions and ideas I have gotten from some above posts. Maybe with new insight I can find something I missed before!

      Thank you very much!

        Pipe the output from the script to an .html file, then view the file in a browser to see the rendered version. I very often do the equivalent of this while developing and debugging web code to check that the rendered page is correct.

        True laziness is hard work
Re: Does __END__ really mean ignore rest of lines?
by Anonymous Monk on Jan 17, 2011 at 18:14 UTC