⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch33.htm

📁 《Perl 5 Unreleased》
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML>



<HEAD>

   <TITLE>Chapter 33 -- Debugging CGI Applications</TITLE>

   <META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">

</HEAD>

<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">

<H1><FONT COLOR=#FF0000>Chapter 33</FONT></H1>

<H1><B><FONT SIZE=5 COLOR=#FF0000>Dynamic Image Creation</FONT></B>

</H1>

<P>

<HR WIDTH="100%"></P>

<P>

<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>

</FONT></FONT></H3>

<UL>

<LI><A HREF="#WrongPermissionsonCGIScripts" >Wrong Permissions on CGI Scripts</A>

<UL>

<LI><A HREF="#CheckingReturnedValuesfromScripts" >Checking Returned Values from Scripts</A>

<LI><A HREF="#CheckingErrorsWhenOpeningFiles" >Checking Errors When Opening Files</A>

<LI><A HREF="#DebugYourCGIScript" >Debug Your CGI Script</A>

<LI><A HREF="#CheckingErrorsWhenOpeningPipes" >Checking Errors When Opening Pipes</A>

<li><a href="#SendMail">Send Mail to Valid Recipients</a></UL>

<LI><A HREF="#UsethePerlInterpreterLineonUNIXSy" >Use the Perl Interpreter Line on UNIX Systems</A>

<LI><A HREF="#LibrariesforDynamicallyLoadedModules" >Libraries for Dynamically Loaded Modules</A>

<LI><A HREF="#CheckforSupportforSystemCalls" >Check for Support for System Calls</A>

<LI><A HREF="#DontReturnMalformedHeaders" >Don't Return Malformed Headers</A>

<LI><A HREF="#FlushOutputBuffersImmediately" >Flush Output Buffers Immediately</A>

<LI><A HREF="#DontSetEnvironmentVariables" >Don't Set Environment Variables</A>

<LI><A HREF="#CleanUpAfterYourself" >Clean Up After Yourself</A>

<LI><A HREF="#ConfigureYourServerCorrectly" >Configure Your Server Correctly</A>

<LI><A HREF="#AlwaysCreateanindexhtmlFile" >Always Create an index.html File</A>

<LI><A HREF="#Summary" >Summary</A>

</UL>

<HR>

<P>

This chapter is devoted to providing solutions to some of the

most common bugs you'll run across when debugging CGI applications.

The information in this chapter is the result of many frustrating

hours spent figuring out why an obviously simple CGI script would

not work. Hopefully, the information in this chapter will solve

some of the problems you might face while debugging CGI scripts.

The information in this chapter is based on topics covered in

<A HREF="ch20.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch20.htm" >Chapter 20</A>, &quot;Introduction to Web

Pages and CGI.&quot;

<P>

Basically, this chapter will cover the points to keep in mind

when you write CGI scripts that have to open files or pipes or

keep temporary information in files, as well issues about how

to respond to client-side requests. We will also cover some security

issues about writing and placing Perl scripts in directory trees.

The summary at the end of the chapter will serve as a good checklist

for you to use when evaluating potential problems with your Perl

CGI scripts.

<H2><A NAME="WrongPermissionsonCGIScripts"><B><FONT SIZE=5 COLOR=#FF0000>Wrong

Permissions on CGI Scripts</FONT></B></A></H2>

<P>

The CGI script on the server side must be an executable file and

have execute permissions set for the file. Not having the correct

permissions results in &quot;file not found&quot; errors sent

back to the client. Not having execute permissions results in

other error messages being sent back to the client.

<H3><A NAME="CheckingReturnedValuesfromScripts"><B>Checking Returned

Values from Scripts</B></A></H3>

<P>

All paths of execution in the CGI script must return a value that

can be interpreted by the client. Test your CGI to make sure that

the application does not exit with an unpredictable return code.

If the CGI script relies on files on the server side, are they

accessible? The CGI script will be running under the same permissions

as the Web server. The server runs as the user called &quot;nobody.&quot;

Make sure that the data files being accessed by the CGI script

have the correct read/write permissions for being accessed by

&quot;nobody.&quot;

<H3><A NAME="CheckingErrorsWhenOpeningFiles"><B>Checking Errors

When Opening Files</B></A></H3>

<P>

Opening the file usually entails checking for errors before proceeding.

Here's a usual call in a Perl script to open a file and read from

it:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">open(MFILE,&quot;&lt;/tmp/bogus/data/file&quot;)

<BR>

|| die &quot;$!: Cannot open it!&quot;;</FONT></TT>

</BLOCKQUOTE>

<P>

If the Perl script skips the error-checking portion and just goes

on attempting to read from the nonexistent file handle <TT><FONT FACE="Courier">MFILE</FONT></TT>,

it will read no data. (Perl does not crash in this instance.)

For example, the following lines are expected to return a GIF

image back to the client:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">print &quot;Content-type:image/gif \n\n&quot;;

<BR>

open(MFILE,&quot;&lt;/tmp/bogus/data/image.file&quot;);<BR>

while (&lt;MFILE&gt;)&nbsp;&nbsp;{<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print $_;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

close MFILE;</FONT></TT>

</BLOCKQUOTE>

<P>

This code would be called in a CGI script to return the contents

of an image back to the browser whose request caused the script

to be executed. If the GIF image being opened does not exist,

then no data is sent back to the browser. Here are the ways to

avoid such errors:

<UL>

<LI><FONT COLOR=#000000>Write some code to make sure that the

data file being read does exist and could be opened.</FONT>

<LI><FONT COLOR=#000000>Return an error message back to the client

if a file cannot be opened or some condition, such as an empty

file, prevents the file from being opened.</FONT>

</UL>

<H3><A NAME="DebugYourCGIScript"><B>Debug Your CGI Script</B></A>

</H3>

<P>

One important thing to look for are possible infinite loops. Make

sure your CGI script always returns. Remember that CGI scripts

are run as the result of a client request coming to your server.

It's quite possible to have several clients make the same request

to start off these infinitely looping CGI scripts on your server.

Too many of these scripts will cause the machine running the server

to lock up!

<H3><A NAME="CheckingErrorsWhenOpeningPipes"><B>Checking Errors

When Opening Pipes</B></A></H3>

<P>

Another common mistake when writing CGI scripts is to use the

error from a pipe command directly. The returned code from a pipe

command is based on whether or not the pipe was opened. The returned

code from the pipe command has nothing to do with the command

on either side of the pipe symbols (<TT><FONT FACE="Courier">|</FONT></TT>).

For example, the following code will almost never execute the

<TT><FONT FACE="Courier">die</FONT></TT> statement because a pipe

almost always can be opened on a given system:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">open(MYFILE,&quot;myprogram |&quot;)

|| die &quot;Cannot run myprogram&quot;;</FONT></TT>

</BLOCKQUOTE>

<P>

Instead, break this statement into two statements and then close

the file handle. The relevant error code will be in the variable

(<TT><FONT FACE="Courier">$?</FONT></TT>) in case of any errors.

Use the error code returned from the <TT><FONT FACE="Courier">close</FONT></TT>

call before proceeding with the second portion of the code. If

there are no errors, reopen the file and continue. This procedure

sounds really hokey, but it works as long as you keep two things

in mind: that starting up <TT><FONT FACE="Courier">myprogram</FONT></TT>

is not inefficient and that each invocation of <TT><FONT FACE="Courier">myprogram</FONT></TT>

is totally unrelated to any previous invocations of <TT><FONT FACE="Courier">myprogram</FONT></TT>.

If these conditions are met, then you can go ahead and simply

structure the code like this:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">open(MYFILE,&quot;myprogram |&quot;);

<BR>

close(MYFILE);<BR>

if ($?)<BR>

{<BR>

die &quot;\n Cannot run myprogram&quot;;<BR>

}<BR>

open(MYFILE,&quot;myprogram |&quot;);</FONT></TT>

</BLOCKQUOTE>

<a name="SendMail"><H3><B>Sending Mail to Valid Recipients</B></H3>

<P>

One way to use CGI scripts is to send mail to a recipient as part

of a response to a <TT><FONT FACE="Courier">FORM</FONT></TT> handler.

For example, the following statements send a mail message using

<TT><FONT FACE="Courier">mailx</FONT></TT>:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">$sendTo = &quot;badguy@bad.code.edu&quot;;

<BR>

#### NO, NO, NO, NOT this way....<BR>

open (MAILME,&quot;| mailx -s 'A report' $sendTo&quot;)<BR>

print MAILME, $mailMessage;<BR>

#<BR>

# some other code here.<BR>

#<BR>

close MAILME;</FONT></TT>

</BLOCKQUOTE>

<P>

When using lines to send mail, make sure you specify the absolute

pathname to the mailer program. Also, close the pipe to the mail

handler as soon as possible; otherwise you might forget to do

so later in the code. Therefore, it's generally better to structure

the previous lines as this:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">$sendTo = &quot;myname@ikra.com&quot;;

<BR>

open (MAILME,&quot;| /usr/bin/mailx -s 'A report' $sendto&quot;)

<BR>

print MAILME, $mailMessage;<BR>

close MAILME;<BR>

#<BR>

# some other code here.<BR>

#</FONT></TT>

</BLOCKQUOTE>

<P>

Of course, you should use your system's mail carrier, such as

<TT><FONT FACE="Courier">mh</FONT></TT>, or<TT><FONT FACE="Courier">

elm</FONT></TT>, instead of <TT><FONT FACE="Courier">mailx</FONT></TT>

in the previous example. Obviously, the underlying mail system

has to be up and running for this to work.

<H2><A NAME="UsethePerlInterpreterLineonUNIXSy"><B><FONT SIZE=5 COLOR=#FF0000>Use

the Perl Interpreter Line on UNIX Systems</FONT></B></A></H2>

<P>

Most CGI applications run on UNIX systems that require the first

line of the CGI script to be a &quot;bang&quot; line. For example,

if your CGI script is a Perl script and your Perl interpreter

is in <TT><FONT FACE="Courier">/usr/local/bin</FONT></TT>, then

the first line of the file should be <TT><FONT FACE="Courier">#!/usr/local/bin/perl</FONT></TT>.

If you don't use this bang line, the default shell script is used

instead, and your CGI script is run by the default shell script.

<P>

On NT systems, the Perl CGI script should not have the bang line

as the first line in the script. The bang line is ignored on NT

systems. The CGI script should run on the NT machine without any

problems. However, when porting CGI scripts from an NT system

to a UNIX system, make sure you add the <TT><FONT FACE="Courier">#!</FONT></TT>

line to the first line of every Perl CGI script.

<H2><A NAME="LibrariesforDynamicallyLoadedModules"><B><FONT SIZE=5 COLOR=#FF0000>Libraries

for Dynamically Loaded Modules</FONT></B></A></H2>

<P>

Some Perl scripts use the <TT><FONT FACE="Courier">Autoload.pm</FONT></TT>

module to dynamically load in extensions at execution time. A

Perl script will not run if the module cannot dynamically load

the extensions. When porting such scripts to different systems,

ensure that the extensions you have to load are available on each

system you port your Perl script to. Some modules may not be available

on the base system you port your CGI script to.

<P>

To avoid such problems at load time, you can either port the modules

yourself, not use the module extensions, or statically link the

extensions in. For example, most modules are statically linked

into the NT version of Perl because the <TT><FONT FACE="Courier">autoload</FONT></TT>

module is not supported under NT. If you are certain that the

modules you are loading are not dynamically linked executables

and that all the functionality you need is in the <TT><FONT FACE="Courier">.pm

</FONT></TT>file, then you can simply use the <TT><FONT FACE="Courier">use</FONT></TT>

statement to load the <TT><FONT FACE="Courier">.pm</FONT></TT>

module file.

<H2><A NAME="CheckforSupportforSystemCalls"><B><FONT SIZE=5 COLOR=#FF0000>Check

for Support for System Calls</FONT></B></A></H2>

<P>

Avoid system calls as much as possible when writing CGI scripts

that have to run on different systems. As its name suggests, a

system call is very dependent on the type of system on which it's

being called. Most versions of UNIX support system calls uniformly

and do not cause any problems. Different operating systems support

different types of system calls. A system call that works on a

VMS system might not work on a UNIX system, and vice versa.

<H2><A NAME="DontReturnMalformedHeaders"><B><FONT SIZE=5 COLOR=#FF0000>Don't

Return Malformed Headers</FONT></B></A></H2>

<P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -