📄 ch15_03.htm
字号:
<?label 15.3. Debugging Tools?><html><head><title>Debugging Tools (CGI Programming with Perl)</title><link href="../style/style1.css" type="text/css" rel="stylesheet" /><meta name="DC.Creator" content="Scott Guelich, Gunther Birznieks and Shishir Gundavaram" /><meta scheme="MIME" content="text/xml" name="DC.Format" /><meta content="en-US" name="DC.Language" /><meta content="O'Reilly & Associates, Inc." name="DC.Publisher" /><meta scheme="ISBN" name="DC.Source" content="1565924193L" /><meta name="DC.Subject.Keyword" content="stuff" /><meta name="DC.Title" content="CGI Programming with Perl" /><meta content="Text.Monograph" name="DC.Type" /></head><body bgcolor="#ffffff"><img src="gifs/smbanner.gif" alt="Book Home" usemap="#banner-map" border="0" /><map name="banner-map"><area alt="CGI Programming with Perl" href="index.htm" coords="0,0,466,65" shape="rect" /><area alt="Search this book" href="jobjects/fsearch.htm" coords="467,0,514,18" shape="rect" /></map><div class="navbar"><table border="0" width="515"><tr><td width="172" valign="top" align="left"><a href="ch15_02.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0" /></a></td><td width="171" valign="top" align="center"><a href="index.htm">CGI Programming with Perl</a></td><td width="172" valign="top" align="right"><a href="ch16_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0" /></a></td></tr></table></div><hr align="left" width="515" /><h2 class="sect1">15.3. Debugging Tools</h2><p>We've looked <a name="INDEX-3032" /><a name="INDEX-3033" />at what can cause common errors, but noteverything is a common problem. If you are having problems and noneof the earlier solutions helps, then you need to do someinvestigative work. In this section, we'll look at some toolsto help you uncover the source of the problem. Briefly, here is anoutline of the steps you can take:</p><ul><li><p>Check the syntax of your scripts with the<a name="INDEX-3034" /><em class="emphasis">-c</em> flag.</p></li><li><p>Check the web server's error logs.</p></li><li><p>Run your script from the command line.</p></li><li><p>Test the value of variables by dumping them to the browser.</p></li><li><p>Use an <a name="INDEX-3035" />interactive debugger.</p></li></ul><p>Let's review each in more detail.</p><a name="ch15-13-fm2xml" /><div class="sect2"><h3 class="sect2">15.3.1. Check Syntax</h3><p>We mentioned this within<a name="INDEX-3036" />one of the sections above, but itbears repeating again in its own section: if your code does not parseor compile, then it will never run correctly. So get in the habit oftesting your scripts with the <em class="emphasis">-c</em> flag from thecommand line before you test them in the browser, and whileyou're add it, have it check for<a name="INDEX-3037" />warnings too with the<em class="emphasis">-w</em> flag. Remember, if you use taint mode (andyou are using taint mode with all of your scripts, right?), you alsoneed to pass the <em class="emphasis">-T</em> flag to avoid the followingerror:</p><blockquote><pre class="code">$ perl -wc myScript.cgiToo late for "-T" option.</pre></blockquote><p>Therefore, use the <tt class="literal">-wcT</tt> combination:</p><blockquote><pre class="code">perl -wcT calendar.cgi</pre></blockquote><p>This will either return:</p><blockquote><pre class="code">Syntax OK</pre></blockquote><p>or a list of problems. Of course you should only use the<em class="emphasis">-c</em> flag from the command line and<em class="emphasis">not</em> add it to the <a name="INDEX-3038" />pound-bang line in your scripts.</p></div><a name="ch15-14-fm2xml" /><div class="sect2"><h3 class="sect2">15.3.2. Check Error Logs</h3><p>Typically, errors are printed to <a name="INDEX-3039" />STDERR, and on<a name="INDEX-3040" /><a name="INDEX-3041" /> <a name="INDEX-3042" />some web servers anything that isprinted to STDERR while a CGI script is running ends up in yourserver's error logs. Thus, you can often find all sorts ofuseful clues by scanning these logs when you have problems. Possiblelocations of this file with <a name="INDEX-3043" />Apache are<em class="filename">/usr/local/apache/logs/error_log</em> or<em class="filename">/usr/var/logs/httpd/error_log</em>. Errors areappended to the bottom; you may want to watch the log as you testyour CGI script. If you use the <tt class="command">tail</tt> command witha <em class="emphasis">-f</em> option:</p><blockquote><pre class="code">$ tail -f /usr/local/apache/logs/error_log</pre></blockquote><p>it will print new lines as they are written to the file.</p></div><a name="ch15-15-fm2xml" /><div class="sect2"><h3 class="sect2">15.3.3. Running Scripts from the Command Line</h3><p>Once your <a name="INDEX-3044" />scripts pass a syntaxcheck, the next step is to try to run them from the command line.Remember that because CGI scripts receive much of their data from<a name="INDEX-3045" />environmentvariables, you can set these manually yourself before you run yourscript:</p><blockquote><pre class="code">$ export HTTP_COOKIE="user_id=abc123"$ export QUERY_STRING="month=jan&year=2001"$ export REQUEST_METHOD="GET"$ ./calendar.cgi</pre></blockquote><p>You will see the full output of your script including any headers youprint. This can be quite useful if you suspect your problem has to dowith the headers you are sending.</p><p>If you are using Version 2.56 or previous of<a name="INDEX-3046" /><a name="INDEX-3047" /><a name="INDEX-3048" />CGI.pm, it makesaccepting form parameters much easier, by prompting for them when yourun your script:</p><blockquote><pre class="code">(offline mode: enter name=value pairs on standard input)</pre></blockquote><p>You can then enter <a name="INDEX-3049" /> <a name="INDEX-3050" />parameters as name-value pairsseparated by an equals sign. CGI.pm ignores whitespace and allows youto use <a name="INDEX-3051" />quotes:</p><blockquote><pre class="code">(offline mode: enter name=value pairs on standard input)month = janyear=2001</pre></blockquote><p>When you are finished, press the <a name="INDEX-3052" /><a name="INDEX-3053" />end-of-file character on yoursystem (use Ctrl-D on Unix or Mac; use Ctrl-Z on Windows).</p><p>As of <a name="INDEX-3054" /><a name="INDEX-3055" />2.57, CGI.pm nolonger automatically prompts for values. Instead, you can passparameters as arguments to your script (this works for previousversions, too):</p><blockquote><pre class="code">$ ./calendar.cgi month=jan year=2001</pre></blockquote><p>If you prefer to have CGI.pm prompt you for input instead, you canstill enable this in later versions by using the<tt class="literal">-debug</tt><a name="INDEX-3056" /> argument with CGI.pm:</p><blockquote><pre class="code">use CGI qw( -debug );</pre></blockquote><p>If you are working with a complex<a name="INDEX-3057" /><a name="INDEX-3058" />form, and it is too much workto manually enter parameters, then you can capture the parameters toa file to use offline by adding a few lines to the top of yourscript:</p><blockquote><pre class="code">#!/usr/bin/perl -wTuse strict;use CGI;my $q = new CGI;## BEGIN INSERTED CODEopen FILE, "> /tmp/query1" or die $!;$q->save( \*FILE );print $q->header( "text/plain" ), "File saved\n";## END INSERTED CODE..</pre></blockquote><p>Now you should have a file saved to <em class="filename">/tmp/query1</em>which you can use from the command line. Remove the inserted codefirst (or comment it out for future use), then you can use the queryfile like this:</p><blockquote><pre class="code">$ ./catalog.cgi < /tmp/query1</pre></blockquote></div><a name="ch15-16-fm2xml" /><div class="sect2"><h3 class="sect2">15.3.4. Dumping Variables</h3><p>If you script runs<a name="INDEX-3059" /> <a name="INDEX-3060" /> <a name="INDEX-3061" />correctly but it does notdo what you expect, then you need to break it down into chunks todetermine where it is failing. The simplest way to do this is toinclude a handful of<tt class="function">print</tt><a name="INDEX-3062" /> statements:</p><blockquote><pre class="code">sub fetch_results {print "Entering fetch_results( @_ )\n"; #DEBUG# . .</pre></blockquote><p>You may want to outdent these commands or place comments at the endso that it is easy to find and remove them when you are done.</p><p>If you are working with a complex <a name="INDEX-3063" /> <a name="INDEX-3064" /><a name="INDEX-3065" />Perl data structure, youcan print it quite easily by using the<a name="INDEX-3066" /><a name="INDEX-3067" />Data::Dumpermodule. Simply add code like the following:</p><blockquote><pre class="code">. .use Data::Dumper; #DEBUG#print Dumper( $result ); #DEBUG# return $result;}</pre></blockquote><p>The <tt class="function">Dumper</tt> function will serialize your datastructure into neatly indented Perl source code. If you want to lookat this within an <a name="INDEX-3068" /> <a name="INDEX-3069" /><a name="INDEX-3070" />HTMLpage, be sure to enclose it within <PRE> tags or view the pagesource.</p><p>If you are outputting complex HTML, you may need to view the sourcein order to see whether your statements printed. It is often mucheasier to open a separate filehandle to your own log file and printyour debugging commands there. In fact, you may want to develop yourown module that provides a way to send debugging output to a commondebug log file as well as a simple way to turn debugging mode on andoff.</p></div><a name="ch15-17-fm2xml" /><div class="sect2"><h3 class="sect2">15.3.5. Debuggers</h3><p>All the previous strategies help isolate bugs, but the best solutionby far is to use debuggers. <a name="INDEX-3071" />Debuggersallow you to interact with your program as it runs. You can monitorthe program flow, watch the value of variables, and more.</p><a name="ch15-18-fm2xml" /><div class="sect3"><h3 class="sect3">15.3.5.1. The Perl debugger</h3><p>If you <a name="INDEX-3072" /><a name="INDEX-3073" />invoke<tt class="command">perl</tt> with the <em class="emphasis">-d</em> flag, youwill end up in an interactive session. Unfortunately, this means thatyou can use the debugger only from the <a name="INDEX-3074" />command line. This is not the traditionalenvironment for CGI scripts, but it is not difficult to mimic the CGIenvironment, as we saw earlier. The best way to do this is to save aCGI object to a query file, initialize any additional environmentvariables you might need, such as cookies, and then run your CGIscript like this:</p><blockquote><pre class="code">$perl -dT calendar.cgi </tmp/query1Loading DB routines from perl5db.pl version 1Emacs support available.Enter h or `h h' for help.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -