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

Hi Monks, I have finished a cgi script and tested in on the command line. Then I put it into the cgi-bin on my web server, set the permissions to 755 owner root. When I execute the cgi script in the browser I get the following error:
Internal Server Error The server encountered an internal error or misconfiguration and was u +nable to complete your request.
I looked in the errorlog for the apache server and found the following error:
Thu Feb 12 02:02:41 1998] [error] (2)No such file or directory: exec o +f /var/www/cgi-bin/generateStatistics.cgi failed Thu Feb 12 02:02:41 1998] [error] [client 213.237.88.236] Premature en +d of script headers: /var/www/cgi-bin/generateStatistics.cgi
Do any of you gurus know what could be wrong? I also executed the cgi script and redirected the output to out.html and I had no problem viewing it in the browser. Here is the cgi code:
#!/usr/bin/perl open (IN_RESULT,"statistics.txt"); @IN_RESULT = <IN_RESULT>; close (IN_RESULT); @armyImages = ('"images/icon_army_dwarf.gif"', '"images/icon_army_empire.gif"', '"images/icon_army_lizard.gif"', '"images/icon_army_orcs.gif"', '"images/icon_army_skaven.gif"' ); print <<WEB_PAGE; <html> <head> <title>Statistics</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1 +"> <STYLE> <!-- A{text-decoration:none} --> </STYLE> <style> body { scrollbar-base-color: #000000; } </style> </head> <body bgcolor="#000000" text="#E6941A" background="images/background2. +gif"> <table width="0" border="0" cellpadding="0" cellspacing="0" height="0" +> <tr> <td width="6" height="6"><img src="images/menu_top_left_border.gif +" width="6" height="6"></td> <td width="118" height="6"><img src="images/menu_top_border.gif" w +idth="118" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="6"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="10" height="6"><img src="images/menu_top_right_border.g +if" width="6" height="6"></td> </tr> <tr> <td width="6" height="25"><img src="images/menu_side_border.gif" w +idth="6" height="37"></td> <td width="118" height="25"><a href="javascript: window.open('stat +istics_administrator.htm','','status=yes, width=600,height=300'); voi +d('');"><img src="images/statistics_icon.gif" width="118" height="36" + border="0"></a></td> <td width="85" height="25"><img src="images/flag_massacre_victory. +gif" width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_major_victory.gif +" width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_minor_victory.gif +" width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_draw.gif" width=" +85" height="36"></td> <td width="85" height="25"><img src="images/flag_minor_defeat.gif" + width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_major_defeat.gif" + width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_massacre_defeat.g +if" width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_total_victories.g +if" width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_total_defeats.gif +" width="85" height="36"></td> <td width="85" height="25"><img src="images/flag_total_battles.gif +" width="85" height="36"></td> <td width="10" height="25"><img src="images/menu_side_border.gif" +width="6" height="37"></td> </tr> WEB_PAGE $imageCount = 0; foreach $entry (@IN_RESULT) { @current = split (':',$entry); print <<WEB_PAGE; <tr> <td width="6"><img src="images/menu_side_border.gif" width="6" hei +ght="37"></td> <td width="118"><img src=@armyImages[$imageCount] width="85" heigh +t="36"></td> <td width="85" align="center" valign="middle">@current[1]</td> <td width="85" align="center" valign="middle">@current[2]</td> <td width="85" align="center" valign="middle">@current[3]</td> <td width="85" align="center" valign="middle">@current[4]</td> <td width="85" align="center" valign="middle">@current[5]</td> <td width="85" align="center" valign="middle">@current[6]</td> <td width="85" align="center" valign="middle">@current[7]</td> <td width="85" align="center" valign="middle">@current[8]</td> <td width="85" align="center" valign="middle">@current[9]</td> <td width="85" align="center" valign="middle">@current[10]</td> <td width="10"><img src="images/menu_side_border.gif" width="6" he +ight="37"></td> </tr> WEB_PAGE $count++; } print <<WEB_PAGE; <tr> <td width="6" height="2"><img src="images/menu_buttom_left_border. +gif" width="6" height="6"></td> <td width="118" height="2"><img src="images/menu_top_border.gif" w +idth="118" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="85" height="2"><img src="images/menu_side_border_medium +.gif" width="85" height="6"></td> <td width="10" height="2"><img src="images/menu_buttom_right_borde +r.gif" width="6" height="6"></td> </tr> </table> <p>&nbsp;</p> <p>&nbsp;</p> </body> </html> WEB_PAGE
Thanks!

Replies are listed 'Best First'.
(Ovid) Re: Apache+cgi problem
by Ovid (Cardinal) on Feb 16, 2002 at 15:13 UTC

    You're not printing a header:

    #!/usr/bin/perl -wT use strict; use CGI qw/ :standard /; my $stats = 'statistics.txt'; open IN_RESULT,"< $stats" or die "Cannot open $stats for reading: $!"; my @in_result = <IN_RESULT>; close (IN_RESULT); my @armyImages = ( '"images/icon_army_dwarf.gif"', '"images/icon_army_empire.gif"', '"images/icon_army_lizard.gif"', '"images/icon_army_orcs.gif"', '"images/icon_army_skaven.gif"' ); print header; print <<WEB_PAGE; . . .

    Note that I added the "standard" stuff and made a change or two.

    • I added use CGI. It's overkill here, though, so you could get away with print "Content-type: text/html\n\n"
    • I added strict. If you're not sure why you need strict, then you need it.
    • I also turned on warnings and taint checking. Taint checking doesn't seem useful here, but you are reading from an external source and if this program gets expanded, it could really protect you at some point.
    • I added a test to see if your file open succeeded. If you have a silent failure, your script would still run and you might have a hard time figuring out why.
    • I changed the name of your array to lower case to avoid confusion with the filehandle.
    • I printed the header -- which is they key issue here.

    I have to admit, from the names of your images, I'm very curious to see what you're putting together :)

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Not sure how to say this without sounding as if I am nitpicking an otherwise great post (++), but ah well, I feel bold.

      I just would like to point out that while "Content-type: text/html\n\n" works often, if you are gonna do that instead of useing CGI, you should really end the lines with double "\015\012" instead, like this:print "Content-type: text/html\015\012\015\012";.

      This is more cross-platform, and would work on most machines, except (I think ) VMS and non-ASCII machines. "\015\012" is the defined CRLF sequence for HTTP-headers.

      In reality though, I think that it is just as good to get into the habit of useing the CGI module right away. Just like you say. It takes care of all such concerns. :)

        I can't find the link, but I seem to recall a response from Tom Christiansen to Abigail where he points out that the line endings are typically a non-issue. This is due to this being such a ubiquitous issue that every Web server (that I am aware of) checks the line endings and adjusts them as necessary. Otherwise, the vast majority of scripts ported to another OS could potentially die a horrible death.

        Cheers,
        Ovid

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Thanks Ovid, The cgi script is now working (after some rework using strict). The program is a warhammer fantasy statistics generator. It's in the beta-beta phase, but can be viewed at: www.skullport.dk/warhammer.htm. The script works but caused me another very strange problem that probably has nothing to do with the cgi script. When viewing "normal" html my images show ok, but the html images generated from the cgi script does not show at all even though the path is the same. Very wierd. Thanks a lot for the help.
Re: Apache+cgi problem
by Zaxo (Archbishop) on Feb 16, 2002 at 15:03 UTC

    Three obvious places to look:

    1. Is perl at /usr/bin/perl?
    2. Does your cgi file have a Ctrl-M tacked onto the shebang line?
    3. Is the winner, I think. Try an absolute path to statistics.txt.
    Additionally, you aren't printing the http headers.

    Update: ++Ovid's reply, warnings, strict and taint mode will help you a lot.

    Update2: RuneK, minimally, print "Content-type: text/html\n\n"; will do, but the CGI::header() call Ovid suggests is better. Ctrl-M sometimes creeps in at the end of the line when documents are produced on DOS/Windows, and transferred in binary mode to *nix servers. For a Windows user, the simplest way to fix that is to upload again in text mode.

    After Compline,
    Zaxo

    A reply falls below the community's threshold of quality. You may see it by logging in.
(cLive ;-) Re: Apache+cgi problem
by cLive ;-) (Prior) on Feb 16, 2002 at 18:03 UTC
    Something I'm surprised Ovid didn't suggest. When debugging a CGI script, it's also a good idea to add:
    use CGI::Carp 'fatalsToBrowser';
    to the beginning of the script. If the script runs OK from the shell, this catches *most* other errors and conveniently displays them in your web browser.

    Have a play and see what you think.

    cLive ;-)

    --
    seek(JOB,$$LA,0);

Re: Apache+cgi problem
by Stegalex (Chaplain) on Feb 17, 2002 at 17:52 UTC
    Hi Monks, I have finished a cgi script and tested in on the command line. Then I put it into the cgi-bin on my web server, set the permissions to 755 owner root.

    You should not let cgi scripts be owned by root. Chown nobody:nobody script. I like chicken.
      This is very bad advice. Two rules of good security:
      • No files should be owned by nobody. This UID is used by many daemons. If they are compromised then those files can overwriten which can help attacker to gain more access to the system.
      • root as owner of cgi script is fine (or any other UID != UID under which Apache runs). This ensures that if either Apache or cgi script is compromised cgi script itself cannot be modified by attacker. The only problem with root as owner of cgi script is that it forces to use root account to update those files. It is better to use another account for this task.

      --
      Ilya Martynov (http://martynov.org/)

Re: Apache+cgi problem
by Stegalex (Chaplain) on Feb 16, 2002 at 15:42 UTC
    Me too! You're not printing your header. Fix it and you shall be happy. I am happy. I like chicken.