I have a Perl script that isn't working and I don't know how to start narrowing down the problem. What can I do?
我有一个不工作的Perl脚本,我不知道如何开始缩小问题。我能做什么?
Note: I'm adding the question because I really want to add my very lengthy answer to *. I keep externally linking to it in other answers and it deserves to be here. Don't be shy about editing my answer if you have something to add.
注意:我之所以添加这个问题,是因为我真的想为*添加一个很长的答案。在其他答案中,我一直把它和它联系在一起,它应该在这里。如果你有什么要补充的,不要羞于编辑我的答案。
8 个解决方案
#1
119
This answer is intended as a general framework for working through problems with Perl CGI scripts and originally appeared on Perlmonks as Troubleshooting Perl CGI Scripts. It is not a complete guide to every problem that you may encounter, nor a tutorial on bug squashing. It is just the culmination of my experience debugging CGI scripts for ten (plus!) years. This page seems to have had many different homes, and I seem to forget it exists, so I'm adding it to the *. You can send any comments or suggestions to me at bdfoy@cpan.org. It's also community wiki, but don't go too nuts. :)
这个答案是用于处理Perl CGI脚本问题的通用框架,最初出现在Perlmonks作为Perl CGI脚本疑难解答时。它不是您可能遇到的所有问题的完整指南,也不是关于bug压缩的教程。这是我十年来调试CGI脚本的经验的顶峰。这个页面似乎有很多不同的家庭,我似乎忘记了它的存在,所以我将它添加到*中。您可以通过bdfoy@cpan.org向我发送任何评论或建议。它也是社区维基,但不要太疯狂。:)
Are you using Perl's built in features to help you find problems?
Turn on warnings to let Perl warn you about questionable parts of your code. You can do this from the command line with the -w
switch so you don't have to change any code or add a pragma to every file:
打开警告,让Perl警告您代码中可疑的部分。您可以从命令行中使用-w开关来完成这一操作,这样您就不必更改任何代码,也不必为每个文件添加一个pragma:
% perl -w program.pl
However, you should force yourself to always clear up questionable code by adding the warnings
pragma to all of your files:
但是,您应该通过在所有文件中添加警告实用程序来强制自己始终清除有问题的代码:
use warnings;
If you need more information than the short warning message, use the diagnostics
pragma to get more information, or look in the perldiag documentation:
如果您需要比短警告消息更多的信息,请使用诊断实用程序获取更多信息,或者查看perldiag文档:
use diagnostics;
Did you output a valid CGI header first?
The server is expecting the first output from a CGI script to be the CGI header. Typically that might be as simple as print "Content-type: text/plain\n\n";
or with CGI.pm and its derivatives, print header()
. Some servers are sensitive to error output (on STDERR
) showing up before standard output (on STDOUT
).
服务器期望CGI脚本的第一个输出是CGI头。通常,这可能和打印“内容类型:文本/普通\n\n”一样简单;或CGI。pm及其衍生物打印头()。有些服务器对错误输出(STDERR上)敏感,在标准输出(STDOUT上)之前出现。
Try sending errors to the browser
Add the line
添加一行
use CGI::Carp 'fatalsToBrowser';
to your script. This also sends compilation errors to the browser window. Be sure to remove this before moving to a production environment, as the extra information can be a security risk.
你的脚本。这也将编译错误发送到浏览器窗口。在转移到生产环境之前,一定要删除它,因为额外的信息可能会带来安全风险。
What did the error log say?
Servers keep error logs (or they should, at least). Error output from the server and from your script should show up there. Find the error log and see what it says. There isn't a standard place for log files. Look in the server configuration for their location, or ask the server admin. You can also use tools such as CGI::Carp to keep your own log files.
服务器保存错误日志(或者至少应该这样)。服务器和脚本的错误输出应该显示在那里。找到错误日志,看看上面写的是什么。没有一个日志文件的标准位置。查看服务器配置的位置,或者询问服务器管理员。您还可以使用CGI: Carp之类的工具来保存自己的日志文件。
What are the script's permissions?
If you see errors like "Permission denied" or "Method not implemented", it probably means that your script is not readable and executable by the web server user. On flavors of Unix, changing the mode to 755 is recommended: chmod 755 filename
. Never set a mode to 777!
如果您看到诸如“拒绝权限”或“未实现方法”之类的错误,可能意味着您的脚本无法被web服务器用户读取和执行。对于Unix的风格,建议将模式更改为755:chmod 755文件名。不要将模式设置为777!
Are you using use strict
?
Remember that Perl automatically creates variables when you first use them. This is a feature, but sometimes can cause bugs if you mistype a variable name. The pragma use strict
will help you find those sorts of errors. It's annoying until you get used to it, but your programming will improve significantly after awhile and you will be free to make different mistakes.
请记住,Perl在首次使用变量时自动创建变量。这是一个特性,但是如果错误地使用变量名,有时会导致错误。pragma使用strict会帮助你发现这类错误。这很烦人,直到你习惯了它,但是你的编程将会在一段时间后得到显著的改善,你将可以*地犯不同的错误。
Does the script compile?
You can check for compilation errors by using the -c
switch. Concentrate on the first errors reported. Rinse, repeat. If you are getting really strange errors, check to ensure that your script has the right line endings. If you FTP in binary mode, checkout from CVS, or something else that does not handle line end translation, the web server may see your script as one big line. Transfer Perl scripts in ASCII mode.
您可以使用-c开关检查编译错误。专注于报告的第一个错误。冲洗,重复。如果您有非常奇怪的错误,请检查以确保您的脚本具有正确的行尾。如果您在二进制模式下FTP,从CVS签出,或者其他不处理行端转换的东西,web服务器可能会将您的脚本视为一条大线。以ASCII模式传输Perl脚本。
Is the script complaining about insecure dependencies?
If your script complains about insecure dependencies, you are probably using the -T
switch to turn on taint mode, which is a good thing since it keeps you have passing unchecked data to the shell. If it is complaining it is doing its job to help us write more secure scripts. Any data originating from outside of the program (i.e. the environment) is considered tainted. Environment variables such as PATH
and LD_LIBRARY_PATH
are particularly troublesome. You have to set these to a safe value or unset them completely, as I recommend. You should be using absolute paths anyway. If taint checking complains about something else, make sure that you have untainted the data. See perlsec man page for details.
如果您的脚本抱怨不安全的依赖关系,那么您可能正在使用-T开关来打开taint模式,这是一件好事,因为它使您能够将未检查的数据传递给shell。如果它抱怨它正在做它的工作,帮助我们编写更安全的脚本。任何来自程序外部(即环境)的数据都被认为是受污染的。像PATH和LD_LIBRARY_PATH这样的环境变量特别麻烦。您必须将它们设置为安全值,或者完全取消设置,就像我建议的那样。你应该使用绝对路径。如果检测有问题,请确保数据没有受到污染。详情请参阅perlsec手册页。
What happens when you run it from the command line?
Does the script output what you expect when run from the command line? Is the header output first, followed by a blank line? Remember that STDERR
may be merged with STDOUT
if you are on a terminal (e.g. an interactive session), and due to buffering may show up in a jumbled order. Turn on Perl's autoflush feature by setting $|
to a true value. Typically you might see $|++;
in CGI programs. Once set, every print and write will immediately go to the output rather than being buffered. You have to set this for each filehandle. Use select
to change the default filehandle, like so:
当从命令行运行时,脚本是否输出您期望的内容?头输出是先输出,然后是空行吗?请记住,如果您在终端(例如交互式会话)上,STDERR可能与STDOUT合并,由于缓冲可能以混乱的顺序出现。通过将$|设置为true值,打开Perl的自动刷新特性。通常您可能会看到$|+;在CGI程序。一旦设置好,所有的打印和写操作将立即转到输出,而不是缓冲。您必须为每个文件句柄设置此值。使用select更改默认的文件句柄,如下所示:
$|++; #sets $| for STDOUT
$old_handle = select( STDERR ); #change to STDERR
$|++; #sets $| for STDERR
select( $old_handle ); #change back to STDOUT
Either way, the first thing output should be the CGI header followed by a blank line.
无论哪种方式,第一个输出应该是CGI头,后面跟着一行空白。
What happens when you run it from the command line with a CGI-like environment?
The web server environment is usually a lot more limited than your command line environment, and has extra information about the request. If your script runs fine from the command line, you might try simulating a web server environment. If the problem appears, you have an environment problem.
web服务器环境通常比命令行环境有更多的限制,并且有关于请求的额外信息。如果脚本从命令行运行良好,您可以尝试模拟web服务器环境。如果出现问题,就会出现环境问题。
Unset or remove these variables
取消或删除这些变量
PATH
- 路径
LD_LIBRARY_PATH
- LD_LIBRARY_PATH
- all
ORACLE_*
variables - 所有ORACLE_ *变量
Set these variables
设置这些变量
-
REQUEST_METHOD
(set toGET
,HEAD
, orPOST
as appropriate) - REQUEST_METHOD(设置为GET、HEAD或POST,视情况而定)
-
SERVER_PORT
(set to 80, usually) - SERVER_PORT(通常设置为80)
-
REMOTE_USER
(if you are doing protected access stuff) - REMOTE_USER(如果您正在进行保护访问)
Recent versions of CGI.pm
( > 2.75 ) require the -debug
flag to get the old (useful) behavior, so you might have to add it to your CGI.pm
imports.
最新版本的CGI。pm(> 2.75)需要-调试标志来获得旧的(有用的)行为,所以您可能需要将它添加到您的CGI中。点进口。
use CGI qw(-debug)
Are you using die()
or warn
?
Those functions print to STDERR
unless you have redefined them. They don't output a CGI header, either. You can get the same functionality with packages such as CGI::Carp
除非重新定义,否则这些函数将输出到STDERR。它们也不输出CGI头。您可以使用CGI::Carp这样的包获得相同的功能
What happens after you clear the browser cache?
If you think your script is doing the right thing, and when you perform the request manually you get the right output, the browser might be the culprit. Clear the cache and set the cache size to zero while testing. Remember that some browsers are really stupid and won't actually reload new content even though you tell it to do so. This is especially prevalent in cases where the URL path is the same, but the content changes (e.g. dynamic images).
如果您认为您的脚本正在做正确的事情,并且当您手工执行请求时,您将得到正确的输出,浏览器可能是罪魁祸首。清除缓存并在测试时将缓存大小设置为0。请记住,有些浏览器非常愚蠢,即使你告诉它这样做,它们也不会重新加载新内容。这在URL路径相同但内容变化(例如动态图像)的情况下尤其普遍。
Is the script where you think it is?
The file system path to a script is not necessarily directly related to the URL path to the script. Make sure you have the right directory, even if you have to write a short test script to test this. Furthermore, are you sure that you are modifying the correct file? If you don't see any effect with your changes, you might be modifying a different file, or uploading a file to the wrong place. (This is, by the way, my most frequent cause of such trouble ;)
脚本的文件系统路径不一定与脚本的URL路径直接相关。确保您有正确的目录,即使您必须编写一个简短的测试脚本来测试它。此外,您确定修改了正确的文件吗?如果您在更改中没有看到任何效果,您可能正在修改另一个文件,或者将文件上传到错误的位置。(顺便说一句,这是我造成这种麻烦的最常见的原因;)
Are you using CGI.pm
, or a derivative of it?
If your problem is related to parsing the CGI input and you aren't using a widely tested module like CGI.pm
, CGI::Request
, CGI::Simple
or CGI::Lite
, use the module and get on with life. CGI.pm
has a cgi-lib.pl
compatibility mode which can help you solve input problems due to older CGI parser implementations.
如果您的问题与解析CGI输入有关,并且您没有使用像CGI这样经过广泛测试的模块。请求,CGI::简单或CGI::Lite,使用模块,继续生活。CGI。下午有一个cgi-lib。pl兼容模式,它可以帮助您解决由于旧的CGI解析器实现而产生的输入问题。
Did you use absolute paths?
If you are running external commands with system
, back ticks, or other IPC facilities, you should use an absolute path to the external program. Not only do you know exactly what you are running, but you avoid some security problems as well. If you are opening files for either reading or writing, use an absolute path. The CGI script may have a different idea about the current directory than you do. Alternatively, you can do an explicit chdir()
to put you in the right place.
如果您正在使用系统、回勾或其他IPC工具运行外部命令,您应该使用到外部程序的绝对路径。您不仅知道您正在运行什么,而且还避免了一些安全问题。如果要打开文件进行读写,请使用绝对路径。CGI脚本可能对当前目录有不同的想法。或者,您可以使用显式chdir()来将您放在正确的位置。
Did you check your return values?
Most Perl functions will tell you if they worked or not and will set $!
on failure. Did you check the return value and examine $!
for error messages? Did you check $@
if you were using eval
?
大多数Perl函数将告诉您它们是否工作,并将设置$!在失败。你检查了返回值并检查了$!错误消息吗?如果使用eval,您是否检查$@ ?
Which version of Perl are you using?
The latest stable version of Perl is 5.16.2. Are you using an older version? Different versions of Perl may have different ideas of warnings.
Perl的最新稳定版本是5.16.2。你使用的是旧版本吗?不同版本的Perl可能有不同的警告思想。
Which web server are you using?
Different servers may act differently in the same situation. The same server product may act differently with different configurations. Include as much of this information as you can in any request for help.
不同的服务器在相同的情况下可能会有不同的行为。相同的服务器产品在不同的配置下可能会有不同的表现。在任何求助请求中尽可能多地包含这些信息。
Did you check the server documentation?
Serious CGI programmers should know as much about the server as possible - including not only the server features and behavior, but also the local configuration. The documentation for your server might not be available to you if you are using a commercial product. Otherwise, the documentation should be on your server. If it isn't, look for it on the web.
认真的CGI程序员应该尽可能多地了解服务器——不仅包括服务器特性和行为,还包括本地配置。如果您使用的是商业产品,服务器的文档可能无法提供。否则,文档应该在您的服务器上。如果不是,在网上找。
Did you search the archives of comp.infosystems.www.authoring.cgi
?
It's likely that someone has had your problem before, and that someone (possibly me) has answered it in this newsgroup. Although this newsgroup has passed its heyday, the collected wisdom from the past can sometimes be useful.
很可能有人以前遇到过你的问题,而有人(可能是我)在这个新闻组里回答了你的问题。虽然这个新闻组已经度过了它的全盛时期,但是从过去收集的智慧有时是有用的。
Can you reproduce the problem with a short test script?
In large systems, it may be difficult to track down a bug since so many things are happening. Try to reproduce the problem behavior with the shortest possible script. Knowing the problem is most of the fix. This may be certainly time-consuming, but you haven't found the problem yet and you're running out of options. :)
在大型系统中,由于发生了许多事情,因此可能很难跟踪错误。尝试用最短的脚本重现问题行为。知道问题所在是解决问题的关键。这可能会很耗时,但你还没有发现问题,你已经没有选择了。:)
Did you decide to go see a movie?
Seriously. Sometimes we can get so wrapped up in the problem that we develop "perceptual narrowing" (tunnel vision). Taking a break, getting a cup of coffee, or blasting some bad guys in [Duke Nukem,Quake,Doom,Halo,COD] might give you the fresh perspective that you need to re-approach the problem.
认真对待。有时我们会被这个问题困得太深,以至于发展出“知觉狭窄”(隧道视觉)。休息一下,喝杯咖啡,或者在[杜克Nukem,Quake,Doom,Halo,COD]里跟一些坏家伙鬼混,可能会给你一个全新的视角,你需要重新面对这个问题。
Have you vocalized the problem?
Seriously again. Sometimes explaining the problem aloud leads us to our own answers. Talk to the penguin (plush toy) because your co-workers aren't listening. If you are interested in this as a serious debugging tool (and I do recommend it if you haven't found the problem by now), you might also like to read The Psychology of Computer Programming.
严重了。有时候大声地解释问题会让我们找到自己的答案。和企鹅(毛绒玩具)说话,因为你的同事不听。如果您对这一重要的调试工具感兴趣(如果您现在还没有发现问题,我确实建议您使用它),那么您可能也希望阅读计算机编程的心理学。
#3
7
die
statements and other fatal run-time and compile-time errors get printed to STDERR
, which can be hard to find and may be conflated with messages from other web pages at your site. While you're debugging your script, it's a good idea to get the fatal error messages to display in your browser somehow.
die语句和其他致命的运行时和编译时错误被打印到STDERR,这可能很难找到,并且可能与站点上其他web页面的消息合并在一起。在调试脚本时,最好在浏览器中以某种方式显示致命的错误消息。
One way to do this is to call
一种方法是打电话
use CGI::Carp qw(fatalsToBrowser);
at the top of your script. That call will install a $SIG{__DIE__}
handler (see perlvar)display fatal errors in your browser, prepending it with a valid header if necessary. Another CGI debugging trick that I used before I ever heard of CGI::Carp
was to use eval
with the DATA
and __END__
facilities on the script to catch compile-time errors:
在脚本的最顶端。这个调用将安装一个$SIG{__di__}处理程序(请参阅perlvar),在浏览器中显示致命错误,如果必要的话,在它前面加上一个有效的头。另一个CGI调试技巧是我在听说过CGI之前使用的::Carp,它使用eval和脚本上的__END__工具来捕获编译时错误:
#!/usr/bin/perl
eval join'', <DATA>;
if ($@) { print "Content-type: text/plain:\n\nError in the script:\n$@\n; }
__DATA__
# ... actual CGI script starts here
This more verbose technique has a slight advantage over CGI::Carp
in that it will catch more compile-time errors.
这种更详细的技术比CGI: Carp有一个小的优点,它可以捕获更多的编译时错误。
Update: I've never used it, but it looks like CGI::Debug
, as Mikael S suggested, is also a very useful and configurable tool for this purpose.
更新:我从未使用过它,但是它看起来像CGI::Debug,正如Mikael S所建议的,也是一个非常有用的、可配置的工具。
#4
7
I wonder how come no-one mentioned the PERLDB_OPTS
option called RemotePort
; although admittedly, there aren't many working examples on the web (RemotePort
isn't even mentioned in perldebug) - and it was kinda problematic for me to come up with this one, but here it goes (it being a Linux example).
我想知道为什么没有人提到叫做RemotePort的PERLDB_OPTS选项;尽管无可否认,在web上并没有很多可用的示例(RemotePort甚至在perldebug中都没有提到)——对于我来说,提出这个示例有点问题,但它是这样的(这是一个Linux示例)。
To do a proper example, first I needed something that can do a very simple simulation of a CGI web server, preferably through a single command line. After finding Simple command line web server for running cgis. (perlmonks.org), I found the IO::All - A Tiny Web Server to be applicable for this test.
为了做一个恰当的示例,首先我需要一个可以对CGI web服务器进行非常简单的模拟的东西,最好是通过一个命令行。找到运行cgis的简单命令行web服务器后。(perlmonks.org),我找到了IO::All——一个适合这个测试的小型Web服务器。
Here, I'll work in the /tmp
directory; the CGI script will be /tmp/test.pl
(included below). Note that the IO::All
server will only serve executable files in the same directory as CGI, so chmod +x test.pl
is required here. So, to do the usual CGI test run, I change directory to /tmp
in the terminal, and run the one-liner web server there:
在这里,我将在/tmp目录中工作;CGI脚本将是/tmp/测试。pl(下面)。注意,IO:::所有服务器将只提供与CGI相同目录中的可执行文件,所以chmod +x测试。pl是必需的。因此,为了进行常规的CGI测试运行,我在终端中将目录更改为/tmp,并在那里运行一行web服务器:
$ cd /tmp
$ perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'
The webserver command will block in the terminal, and will otherwise start the web server locally (on 127.0.0.1 or localhost
) - afterwards, I can go to a web browser, and request this address:
webserver命令将在终端中阻塞,否则将在本地启动web服务器(在127.0.0.1或localhost上)——然后,我可以访问web浏览器,并请求这个地址:
http://127.0.0.1:8080/test.pl
... and I should observe the print
s made by test.pl
being loaded - and shown - in the web browser.
…我还应该观察测试的指纹。正在web浏览器中加载和显示pl。
Now, to debug this script with RemotePort
, first we need a listener on the network, through which we will interact with the Perl debugger; we can use the command line tool netcat
(nc
, saw that here: Perl如何remote debug?). So, first run the netcat
listener in one terminal - where it will block and wait for connections on port 7234 (which will be our debug port):
现在,要用RemotePort调试这个脚本,首先我们需要网络上的一个侦听器,通过它我们将与Perl调试器进行交互;我们可以使用命令行工具netcat(数控,看到这里:Perl如何远程调试?)。因此,首先在一个终端上运行netcat监听器——它将在端口7234上阻塞并等待连接(这将是我们的调试端口):
$ nc -l 7234
Then, we'd want perl
to start in debug mode with RemotePort
, when the test.pl
has been called (even in CGI mode, through the server). This, in Linux, can be done using the following "shebang wrapper" script - which here also needs to be in /tmp
, and must be made executable:
然后,我们希望perl在测试时以RemotePort的调试模式开始。已经调用了pl(甚至在CGI模式下,通过服务器)。在Linux中,这可以使用以下“shebang包装器”脚本完成——这里也需要在/tmp中,并且必须使其可执行:
cd /tmp
cat > perldbgcall.sh <<'EOF'
#!/bin/bash
PERLDB_OPTS="RemotePort=localhost:7234" perl -d -e "do '$@'"
EOF
chmod +x perldbgcall.sh
This is kind of a tricky thing - see shell script - How can I use environment variables in my shebang? - Unix & Linux Stack Exchange. But, the trick here seems to be not to fork the perl
interpreter which handles test.pl
- so once we hit it, we don't exec
, but instead we call perl
"plainly", and basically "source" our test.pl
script using do
(see How do I run a Perl script from within a Perl script?).
这是一件棘手的事情——请参阅shell脚本——我如何在我的shebang中使用环境变量?- Unix和Linux堆栈交换。但是,这里的诀窍似乎是不要使用perl解释器来处理测试。pl -因此,一旦我们碰到它,我们就不执行,而是把perl称为“简单”,基本上是“源代码”我们的测试。使用do(请参见如何在Perl脚本中运行Perl脚本?)
Now that we have perldbgcall.sh
in /tmp
- we can change the test.pl
file, so that it refers to this executable file on its shebang line (instead of the usual Perl interpreter) - here is /tmp/test.pl
modified thus:
现在我们有了perldbgcall。输入/tmp -我们可以更改测试。pl文件,以便它在其shebang行(而不是通常的Perl解释器)上引用这个可执行文件,这里是/tmp/test。pl修改:
#!./perldbgcall.sh
# this is test.pl
use 5.10.1;
use warnings;
use strict;
my $b = '1';
my $a = sub { "hello $b there" };
$b = '2';
print "YEAH " . $a->() . " CMON\n";
$b = '3';
print "CMON " . &$a . " YEAH\n";
$DB::single=1; # BREAKPOINT
$b = '4';
print "STEP " . &$a . " NOW\n";
$b = '5';
print "STEP " . &$a . " AGAIN\n";
Now, both test.pl
and its new shebang handler, perldbgcall.sh
, are in /tmp
; and we have nc
listening for debug connections on port 7234 - so we can finally open another terminal window, change directory to /tmp
, and run the one-liner webserver (which will listen for web connections on port 8080) there:
现在,测试。pl及其新的shebang处理程序perldbgcall。在/ tmp sh,;我们可以在7234端口上监听调试连接,这样我们就可以打开另一个终端窗口,将目录更改为/tmp,并运行一层的webserver(它将监听端口8080上的web连接):
cd /tmp
perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'
After this is done, we can go to our web browser, and request the same address, http://127.0.0.1:8080/test.pl
. However, now when the webserver tries to execute the script, it will do so through perldbgcall.sh
shebang - which will start perl
in remote debugger mode. Thus, the script execution will pause - and so the web browser will lock, waiting for data. We can now switch to the netcat
terminal, and we should see the familiar Perl debugger text - however, output through nc
:
完成之后,我们可以访问web浏览器,并请求相同的地址http://127.0.1:8080 /test.pl。但是,现在当webserver尝试执行脚本时,它将通过perldbgcall执行脚本。它将在远程调试器模式下启动perl。因此,脚本执行将暂停——因此web浏览器将锁定,等待数据。现在我们可以切换到netcat终端,我们应该可以看到熟悉的Perl调试器文本—但是,通过nc输出:
$ nc -l 7234
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(-e:1): do './test.pl'
DB<1> r
main::(./test.pl:29): $b = '4';
DB<1>
As the snippet shows, we now basically use nc
as a "terminal" - so we can type r
(and Enter) for "run" - and the script will run up do the breakpoint statement (see also In perl, what is the difference between $DB::single = 1 and 2?), before stopping again (note at that point, the browser will still lock).
片段显示,我们现在基本上使用数控作为“终端”——我们可以输入r(“运行”,并输入),脚本将断点声明(参见在perl,之间的区别是什么$ DB::单= 1和2 ?),再次停止前(注意在这一点上,浏览器仍然锁)。
So, now we can, say, step through the rest of test.pl
, through the nc
terminal:
所以,现在我们可以,比如说,逐步完成剩下的测试。pl,通过nc终端:
....
main::(./test.pl:29): $b = '4';
DB<1> n
main::(./test.pl:30): print "STEP " . &$a . " NOW\n";
DB<1> n
main::(./test.pl:31): $b = '5';
DB<1> n
main::(./test.pl:32): print "STEP " . &$a . " AGAIN\n";
DB<1> n
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1>
... however, also at this point, the browser locks and waits for data. Only after we exit the debugger with q
:
…然而,同样在这一点上,浏览器锁定并等待数据。只有当我们用q退出调试器后:
DB<1> q
$
... does the browser stop locking - and finally displays the (complete) output of test.pl
:
…浏览器是否停止锁定——并最终显示test.pl的(完整的)输出:
YEAH hello 2 there CMON
CMON hello 3 there YEAH
STEP hello 4 there NOW
STEP hello 5 there AGAIN
Of course, this kind of debug can be done even without running the web server - however, the neat thing here, is that we don't touch the web server at all; we trigger execution "natively" (for CGI) from a web browser - and the only change needed in the CGI script itself, is the change of shebang (and of course, the presence of the shebang wrapper script, as executable file in the same directory).
当然,这种调试可以在不运行web服务器的情况下完成——但是,这里最简单的一点是,我们根本不接触web服务器;我们从web浏览器触发执行“本机”(用于CGI)——以及CGI脚本本身所需要的唯一更改,是shebang的更改(当然,还有shebang包装器脚本的存在,作为同一个目录中的可执行文件)。
Well, hope this helps someone - I sure would have loved to have stumbled upon this, instead of writing it myself :)
Cheers!
好吧,希望这能对某人有所帮助——我当然希望自己无意中发现了这一点,而不是自己写下来:)干杯!
#5
4
For me, I use log4perl . It's quite useful and easy.
对于我来说,我使用log4perl。它很有用,也很简单。
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init( { level => $DEBUG, file => ">>d:\\tokyo.log" } );
my $logger = Log::Log4perl::get_logger();
$logger->debug("your log message");
#6
1
Honestly you can do all the fun stuff above this post. ALTHOUGH, the simplest and most proactive solution I found was to just "print it".
老实说,你可以在这篇文章上面做所有有趣的事情。虽然,我发现最简单和最积极的解决方案是“打印它”。
In example: (Normal code)
在示例:(正常代码)
`$somecommand`;
To see if it's doing what I really want it to do: (Trouble shooting)
看看它是否在做我真正想做的事情:(解决问题)
print "$somecommand";
#7
1
It will probably also be worth mentioning that Perl will always tell you on what line the error occurs when you execute the Perl script from the command line. (An SSH Session for example)
值得一提的是,当您从命令行执行Perl脚本时,Perl总是会告诉您错误发生在什么行。(例如SSH会话)
I will usually do this if all else fails. I will SSH into the server and manually execute the Perl script. For example:
如果其他都失败了,我通常会这样做。我将SSH到服务器并手动执行Perl脚本。例如:
% perl myscript.cgi
If there is a problem then Perl will tell you about it. This debugging method does away with any file permission related issues or web browser or web server issues.
如果有问题,那么Perl会告诉您。此调试方法消除与文件权限相关的任何问题或web浏览器或web服务器问题。
#8
0
You may run the perl cgi-script in terminal using the below command
您可以使用下面的命令在终端中运行perl cgi-script
$ perl filename.cgi
It interpret the code and provide result with HTML code .It will report the error if any.
它解释代码并提供HTML代码的结果,如果有错误,它将报告。
#1
119
This answer is intended as a general framework for working through problems with Perl CGI scripts and originally appeared on Perlmonks as Troubleshooting Perl CGI Scripts. It is not a complete guide to every problem that you may encounter, nor a tutorial on bug squashing. It is just the culmination of my experience debugging CGI scripts for ten (plus!) years. This page seems to have had many different homes, and I seem to forget it exists, so I'm adding it to the *. You can send any comments or suggestions to me at bdfoy@cpan.org. It's also community wiki, but don't go too nuts. :)
这个答案是用于处理Perl CGI脚本问题的通用框架,最初出现在Perlmonks作为Perl CGI脚本疑难解答时。它不是您可能遇到的所有问题的完整指南,也不是关于bug压缩的教程。这是我十年来调试CGI脚本的经验的顶峰。这个页面似乎有很多不同的家庭,我似乎忘记了它的存在,所以我将它添加到*中。您可以通过bdfoy@cpan.org向我发送任何评论或建议。它也是社区维基,但不要太疯狂。:)
Are you using Perl's built in features to help you find problems?
Turn on warnings to let Perl warn you about questionable parts of your code. You can do this from the command line with the -w
switch so you don't have to change any code or add a pragma to every file:
打开警告,让Perl警告您代码中可疑的部分。您可以从命令行中使用-w开关来完成这一操作,这样您就不必更改任何代码,也不必为每个文件添加一个pragma:
% perl -w program.pl
However, you should force yourself to always clear up questionable code by adding the warnings
pragma to all of your files:
但是,您应该通过在所有文件中添加警告实用程序来强制自己始终清除有问题的代码:
use warnings;
If you need more information than the short warning message, use the diagnostics
pragma to get more information, or look in the perldiag documentation:
如果您需要比短警告消息更多的信息,请使用诊断实用程序获取更多信息,或者查看perldiag文档:
use diagnostics;
Did you output a valid CGI header first?
The server is expecting the first output from a CGI script to be the CGI header. Typically that might be as simple as print "Content-type: text/plain\n\n";
or with CGI.pm and its derivatives, print header()
. Some servers are sensitive to error output (on STDERR
) showing up before standard output (on STDOUT
).
服务器期望CGI脚本的第一个输出是CGI头。通常,这可能和打印“内容类型:文本/普通\n\n”一样简单;或CGI。pm及其衍生物打印头()。有些服务器对错误输出(STDERR上)敏感,在标准输出(STDOUT上)之前出现。
Try sending errors to the browser
Add the line
添加一行
use CGI::Carp 'fatalsToBrowser';
to your script. This also sends compilation errors to the browser window. Be sure to remove this before moving to a production environment, as the extra information can be a security risk.
你的脚本。这也将编译错误发送到浏览器窗口。在转移到生产环境之前,一定要删除它,因为额外的信息可能会带来安全风险。
What did the error log say?
Servers keep error logs (or they should, at least). Error output from the server and from your script should show up there. Find the error log and see what it says. There isn't a standard place for log files. Look in the server configuration for their location, or ask the server admin. You can also use tools such as CGI::Carp to keep your own log files.
服务器保存错误日志(或者至少应该这样)。服务器和脚本的错误输出应该显示在那里。找到错误日志,看看上面写的是什么。没有一个日志文件的标准位置。查看服务器配置的位置,或者询问服务器管理员。您还可以使用CGI: Carp之类的工具来保存自己的日志文件。
What are the script's permissions?
If you see errors like "Permission denied" or "Method not implemented", it probably means that your script is not readable and executable by the web server user. On flavors of Unix, changing the mode to 755 is recommended: chmod 755 filename
. Never set a mode to 777!
如果您看到诸如“拒绝权限”或“未实现方法”之类的错误,可能意味着您的脚本无法被web服务器用户读取和执行。对于Unix的风格,建议将模式更改为755:chmod 755文件名。不要将模式设置为777!
Are you using use strict
?
Remember that Perl automatically creates variables when you first use them. This is a feature, but sometimes can cause bugs if you mistype a variable name. The pragma use strict
will help you find those sorts of errors. It's annoying until you get used to it, but your programming will improve significantly after awhile and you will be free to make different mistakes.
请记住,Perl在首次使用变量时自动创建变量。这是一个特性,但是如果错误地使用变量名,有时会导致错误。pragma使用strict会帮助你发现这类错误。这很烦人,直到你习惯了它,但是你的编程将会在一段时间后得到显著的改善,你将可以*地犯不同的错误。
Does the script compile?
You can check for compilation errors by using the -c
switch. Concentrate on the first errors reported. Rinse, repeat. If you are getting really strange errors, check to ensure that your script has the right line endings. If you FTP in binary mode, checkout from CVS, or something else that does not handle line end translation, the web server may see your script as one big line. Transfer Perl scripts in ASCII mode.
您可以使用-c开关检查编译错误。专注于报告的第一个错误。冲洗,重复。如果您有非常奇怪的错误,请检查以确保您的脚本具有正确的行尾。如果您在二进制模式下FTP,从CVS签出,或者其他不处理行端转换的东西,web服务器可能会将您的脚本视为一条大线。以ASCII模式传输Perl脚本。
Is the script complaining about insecure dependencies?
If your script complains about insecure dependencies, you are probably using the -T
switch to turn on taint mode, which is a good thing since it keeps you have passing unchecked data to the shell. If it is complaining it is doing its job to help us write more secure scripts. Any data originating from outside of the program (i.e. the environment) is considered tainted. Environment variables such as PATH
and LD_LIBRARY_PATH
are particularly troublesome. You have to set these to a safe value or unset them completely, as I recommend. You should be using absolute paths anyway. If taint checking complains about something else, make sure that you have untainted the data. See perlsec man page for details.
如果您的脚本抱怨不安全的依赖关系,那么您可能正在使用-T开关来打开taint模式,这是一件好事,因为它使您能够将未检查的数据传递给shell。如果它抱怨它正在做它的工作,帮助我们编写更安全的脚本。任何来自程序外部(即环境)的数据都被认为是受污染的。像PATH和LD_LIBRARY_PATH这样的环境变量特别麻烦。您必须将它们设置为安全值,或者完全取消设置,就像我建议的那样。你应该使用绝对路径。如果检测有问题,请确保数据没有受到污染。详情请参阅perlsec手册页。
What happens when you run it from the command line?
Does the script output what you expect when run from the command line? Is the header output first, followed by a blank line? Remember that STDERR
may be merged with STDOUT
if you are on a terminal (e.g. an interactive session), and due to buffering may show up in a jumbled order. Turn on Perl's autoflush feature by setting $|
to a true value. Typically you might see $|++;
in CGI programs. Once set, every print and write will immediately go to the output rather than being buffered. You have to set this for each filehandle. Use select
to change the default filehandle, like so:
当从命令行运行时,脚本是否输出您期望的内容?头输出是先输出,然后是空行吗?请记住,如果您在终端(例如交互式会话)上,STDERR可能与STDOUT合并,由于缓冲可能以混乱的顺序出现。通过将$|设置为true值,打开Perl的自动刷新特性。通常您可能会看到$|+;在CGI程序。一旦设置好,所有的打印和写操作将立即转到输出,而不是缓冲。您必须为每个文件句柄设置此值。使用select更改默认的文件句柄,如下所示:
$|++; #sets $| for STDOUT
$old_handle = select( STDERR ); #change to STDERR
$|++; #sets $| for STDERR
select( $old_handle ); #change back to STDOUT
Either way, the first thing output should be the CGI header followed by a blank line.
无论哪种方式,第一个输出应该是CGI头,后面跟着一行空白。
What happens when you run it from the command line with a CGI-like environment?
The web server environment is usually a lot more limited than your command line environment, and has extra information about the request. If your script runs fine from the command line, you might try simulating a web server environment. If the problem appears, you have an environment problem.
web服务器环境通常比命令行环境有更多的限制,并且有关于请求的额外信息。如果脚本从命令行运行良好,您可以尝试模拟web服务器环境。如果出现问题,就会出现环境问题。
Unset or remove these variables
取消或删除这些变量
PATH
- 路径
LD_LIBRARY_PATH
- LD_LIBRARY_PATH
- all
ORACLE_*
variables - 所有ORACLE_ *变量
Set these variables
设置这些变量
-
REQUEST_METHOD
(set toGET
,HEAD
, orPOST
as appropriate) - REQUEST_METHOD(设置为GET、HEAD或POST,视情况而定)
-
SERVER_PORT
(set to 80, usually) - SERVER_PORT(通常设置为80)
-
REMOTE_USER
(if you are doing protected access stuff) - REMOTE_USER(如果您正在进行保护访问)
Recent versions of CGI.pm
( > 2.75 ) require the -debug
flag to get the old (useful) behavior, so you might have to add it to your CGI.pm
imports.
最新版本的CGI。pm(> 2.75)需要-调试标志来获得旧的(有用的)行为,所以您可能需要将它添加到您的CGI中。点进口。
use CGI qw(-debug)
Are you using die()
or warn
?
Those functions print to STDERR
unless you have redefined them. They don't output a CGI header, either. You can get the same functionality with packages such as CGI::Carp
除非重新定义,否则这些函数将输出到STDERR。它们也不输出CGI头。您可以使用CGI::Carp这样的包获得相同的功能
What happens after you clear the browser cache?
If you think your script is doing the right thing, and when you perform the request manually you get the right output, the browser might be the culprit. Clear the cache and set the cache size to zero while testing. Remember that some browsers are really stupid and won't actually reload new content even though you tell it to do so. This is especially prevalent in cases where the URL path is the same, but the content changes (e.g. dynamic images).
如果您认为您的脚本正在做正确的事情,并且当您手工执行请求时,您将得到正确的输出,浏览器可能是罪魁祸首。清除缓存并在测试时将缓存大小设置为0。请记住,有些浏览器非常愚蠢,即使你告诉它这样做,它们也不会重新加载新内容。这在URL路径相同但内容变化(例如动态图像)的情况下尤其普遍。
Is the script where you think it is?
The file system path to a script is not necessarily directly related to the URL path to the script. Make sure you have the right directory, even if you have to write a short test script to test this. Furthermore, are you sure that you are modifying the correct file? If you don't see any effect with your changes, you might be modifying a different file, or uploading a file to the wrong place. (This is, by the way, my most frequent cause of such trouble ;)
脚本的文件系统路径不一定与脚本的URL路径直接相关。确保您有正确的目录,即使您必须编写一个简短的测试脚本来测试它。此外,您确定修改了正确的文件吗?如果您在更改中没有看到任何效果,您可能正在修改另一个文件,或者将文件上传到错误的位置。(顺便说一句,这是我造成这种麻烦的最常见的原因;)
Are you using CGI.pm
, or a derivative of it?
If your problem is related to parsing the CGI input and you aren't using a widely tested module like CGI.pm
, CGI::Request
, CGI::Simple
or CGI::Lite
, use the module and get on with life. CGI.pm
has a cgi-lib.pl
compatibility mode which can help you solve input problems due to older CGI parser implementations.
如果您的问题与解析CGI输入有关,并且您没有使用像CGI这样经过广泛测试的模块。请求,CGI::简单或CGI::Lite,使用模块,继续生活。CGI。下午有一个cgi-lib。pl兼容模式,它可以帮助您解决由于旧的CGI解析器实现而产生的输入问题。
Did you use absolute paths?
If you are running external commands with system
, back ticks, or other IPC facilities, you should use an absolute path to the external program. Not only do you know exactly what you are running, but you avoid some security problems as well. If you are opening files for either reading or writing, use an absolute path. The CGI script may have a different idea about the current directory than you do. Alternatively, you can do an explicit chdir()
to put you in the right place.
如果您正在使用系统、回勾或其他IPC工具运行外部命令,您应该使用到外部程序的绝对路径。您不仅知道您正在运行什么,而且还避免了一些安全问题。如果要打开文件进行读写,请使用绝对路径。CGI脚本可能对当前目录有不同的想法。或者,您可以使用显式chdir()来将您放在正确的位置。
Did you check your return values?
Most Perl functions will tell you if they worked or not and will set $!
on failure. Did you check the return value and examine $!
for error messages? Did you check $@
if you were using eval
?
大多数Perl函数将告诉您它们是否工作,并将设置$!在失败。你检查了返回值并检查了$!错误消息吗?如果使用eval,您是否检查$@ ?
Which version of Perl are you using?
The latest stable version of Perl is 5.16.2. Are you using an older version? Different versions of Perl may have different ideas of warnings.
Perl的最新稳定版本是5.16.2。你使用的是旧版本吗?不同版本的Perl可能有不同的警告思想。
Which web server are you using?
Different servers may act differently in the same situation. The same server product may act differently with different configurations. Include as much of this information as you can in any request for help.
不同的服务器在相同的情况下可能会有不同的行为。相同的服务器产品在不同的配置下可能会有不同的表现。在任何求助请求中尽可能多地包含这些信息。
Did you check the server documentation?
Serious CGI programmers should know as much about the server as possible - including not only the server features and behavior, but also the local configuration. The documentation for your server might not be available to you if you are using a commercial product. Otherwise, the documentation should be on your server. If it isn't, look for it on the web.
认真的CGI程序员应该尽可能多地了解服务器——不仅包括服务器特性和行为,还包括本地配置。如果您使用的是商业产品,服务器的文档可能无法提供。否则,文档应该在您的服务器上。如果不是,在网上找。
Did you search the archives of comp.infosystems.www.authoring.cgi
?
It's likely that someone has had your problem before, and that someone (possibly me) has answered it in this newsgroup. Although this newsgroup has passed its heyday, the collected wisdom from the past can sometimes be useful.
很可能有人以前遇到过你的问题,而有人(可能是我)在这个新闻组里回答了你的问题。虽然这个新闻组已经度过了它的全盛时期,但是从过去收集的智慧有时是有用的。
Can you reproduce the problem with a short test script?
In large systems, it may be difficult to track down a bug since so many things are happening. Try to reproduce the problem behavior with the shortest possible script. Knowing the problem is most of the fix. This may be certainly time-consuming, but you haven't found the problem yet and you're running out of options. :)
在大型系统中,由于发生了许多事情,因此可能很难跟踪错误。尝试用最短的脚本重现问题行为。知道问题所在是解决问题的关键。这可能会很耗时,但你还没有发现问题,你已经没有选择了。:)
Did you decide to go see a movie?
Seriously. Sometimes we can get so wrapped up in the problem that we develop "perceptual narrowing" (tunnel vision). Taking a break, getting a cup of coffee, or blasting some bad guys in [Duke Nukem,Quake,Doom,Halo,COD] might give you the fresh perspective that you need to re-approach the problem.
认真对待。有时我们会被这个问题困得太深,以至于发展出“知觉狭窄”(隧道视觉)。休息一下,喝杯咖啡,或者在[杜克Nukem,Quake,Doom,Halo,COD]里跟一些坏家伙鬼混,可能会给你一个全新的视角,你需要重新面对这个问题。
Have you vocalized the problem?
Seriously again. Sometimes explaining the problem aloud leads us to our own answers. Talk to the penguin (plush toy) because your co-workers aren't listening. If you are interested in this as a serious debugging tool (and I do recommend it if you haven't found the problem by now), you might also like to read The Psychology of Computer Programming.
严重了。有时候大声地解释问题会让我们找到自己的答案。和企鹅(毛绒玩具)说话,因为你的同事不听。如果您对这一重要的调试工具感兴趣(如果您现在还没有发现问题,我确实建议您使用它),那么您可能也希望阅读计算机编程的心理学。
#2
#3
7
die
statements and other fatal run-time and compile-time errors get printed to STDERR
, which can be hard to find and may be conflated with messages from other web pages at your site. While you're debugging your script, it's a good idea to get the fatal error messages to display in your browser somehow.
die语句和其他致命的运行时和编译时错误被打印到STDERR,这可能很难找到,并且可能与站点上其他web页面的消息合并在一起。在调试脚本时,最好在浏览器中以某种方式显示致命的错误消息。
One way to do this is to call
一种方法是打电话
use CGI::Carp qw(fatalsToBrowser);
at the top of your script. That call will install a $SIG{__DIE__}
handler (see perlvar)display fatal errors in your browser, prepending it with a valid header if necessary. Another CGI debugging trick that I used before I ever heard of CGI::Carp
was to use eval
with the DATA
and __END__
facilities on the script to catch compile-time errors:
在脚本的最顶端。这个调用将安装一个$SIG{__di__}处理程序(请参阅perlvar),在浏览器中显示致命错误,如果必要的话,在它前面加上一个有效的头。另一个CGI调试技巧是我在听说过CGI之前使用的::Carp,它使用eval和脚本上的__END__工具来捕获编译时错误:
#!/usr/bin/perl
eval join'', <DATA>;
if ($@) { print "Content-type: text/plain:\n\nError in the script:\n$@\n; }
__DATA__
# ... actual CGI script starts here
This more verbose technique has a slight advantage over CGI::Carp
in that it will catch more compile-time errors.
这种更详细的技术比CGI: Carp有一个小的优点,它可以捕获更多的编译时错误。
Update: I've never used it, but it looks like CGI::Debug
, as Mikael S suggested, is also a very useful and configurable tool for this purpose.
更新:我从未使用过它,但是它看起来像CGI::Debug,正如Mikael S所建议的,也是一个非常有用的、可配置的工具。
#4
7
I wonder how come no-one mentioned the PERLDB_OPTS
option called RemotePort
; although admittedly, there aren't many working examples on the web (RemotePort
isn't even mentioned in perldebug) - and it was kinda problematic for me to come up with this one, but here it goes (it being a Linux example).
我想知道为什么没有人提到叫做RemotePort的PERLDB_OPTS选项;尽管无可否认,在web上并没有很多可用的示例(RemotePort甚至在perldebug中都没有提到)——对于我来说,提出这个示例有点问题,但它是这样的(这是一个Linux示例)。
To do a proper example, first I needed something that can do a very simple simulation of a CGI web server, preferably through a single command line. After finding Simple command line web server for running cgis. (perlmonks.org), I found the IO::All - A Tiny Web Server to be applicable for this test.
为了做一个恰当的示例,首先我需要一个可以对CGI web服务器进行非常简单的模拟的东西,最好是通过一个命令行。找到运行cgis的简单命令行web服务器后。(perlmonks.org),我找到了IO::All——一个适合这个测试的小型Web服务器。
Here, I'll work in the /tmp
directory; the CGI script will be /tmp/test.pl
(included below). Note that the IO::All
server will only serve executable files in the same directory as CGI, so chmod +x test.pl
is required here. So, to do the usual CGI test run, I change directory to /tmp
in the terminal, and run the one-liner web server there:
在这里,我将在/tmp目录中工作;CGI脚本将是/tmp/测试。pl(下面)。注意,IO:::所有服务器将只提供与CGI相同目录中的可执行文件,所以chmod +x测试。pl是必需的。因此,为了进行常规的CGI测试运行,我在终端中将目录更改为/tmp,并在那里运行一行web服务器:
$ cd /tmp
$ perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'
The webserver command will block in the terminal, and will otherwise start the web server locally (on 127.0.0.1 or localhost
) - afterwards, I can go to a web browser, and request this address:
webserver命令将在终端中阻塞,否则将在本地启动web服务器(在127.0.0.1或localhost上)——然后,我可以访问web浏览器,并请求这个地址:
http://127.0.0.1:8080/test.pl
... and I should observe the print
s made by test.pl
being loaded - and shown - in the web browser.
…我还应该观察测试的指纹。正在web浏览器中加载和显示pl。
Now, to debug this script with RemotePort
, first we need a listener on the network, through which we will interact with the Perl debugger; we can use the command line tool netcat
(nc
, saw that here: Perl如何remote debug?). So, first run the netcat
listener in one terminal - where it will block and wait for connections on port 7234 (which will be our debug port):
现在,要用RemotePort调试这个脚本,首先我们需要网络上的一个侦听器,通过它我们将与Perl调试器进行交互;我们可以使用命令行工具netcat(数控,看到这里:Perl如何远程调试?)。因此,首先在一个终端上运行netcat监听器——它将在端口7234上阻塞并等待连接(这将是我们的调试端口):
$ nc -l 7234
Then, we'd want perl
to start in debug mode with RemotePort
, when the test.pl
has been called (even in CGI mode, through the server). This, in Linux, can be done using the following "shebang wrapper" script - which here also needs to be in /tmp
, and must be made executable:
然后,我们希望perl在测试时以RemotePort的调试模式开始。已经调用了pl(甚至在CGI模式下,通过服务器)。在Linux中,这可以使用以下“shebang包装器”脚本完成——这里也需要在/tmp中,并且必须使其可执行:
cd /tmp
cat > perldbgcall.sh <<'EOF'
#!/bin/bash
PERLDB_OPTS="RemotePort=localhost:7234" perl -d -e "do '$@'"
EOF
chmod +x perldbgcall.sh
This is kind of a tricky thing - see shell script - How can I use environment variables in my shebang? - Unix & Linux Stack Exchange. But, the trick here seems to be not to fork the perl
interpreter which handles test.pl
- so once we hit it, we don't exec
, but instead we call perl
"plainly", and basically "source" our test.pl
script using do
(see How do I run a Perl script from within a Perl script?).
这是一件棘手的事情——请参阅shell脚本——我如何在我的shebang中使用环境变量?- Unix和Linux堆栈交换。但是,这里的诀窍似乎是不要使用perl解释器来处理测试。pl -因此,一旦我们碰到它,我们就不执行,而是把perl称为“简单”,基本上是“源代码”我们的测试。使用do(请参见如何在Perl脚本中运行Perl脚本?)
Now that we have perldbgcall.sh
in /tmp
- we can change the test.pl
file, so that it refers to this executable file on its shebang line (instead of the usual Perl interpreter) - here is /tmp/test.pl
modified thus:
现在我们有了perldbgcall。输入/tmp -我们可以更改测试。pl文件,以便它在其shebang行(而不是通常的Perl解释器)上引用这个可执行文件,这里是/tmp/test。pl修改:
#!./perldbgcall.sh
# this is test.pl
use 5.10.1;
use warnings;
use strict;
my $b = '1';
my $a = sub { "hello $b there" };
$b = '2';
print "YEAH " . $a->() . " CMON\n";
$b = '3';
print "CMON " . &$a . " YEAH\n";
$DB::single=1; # BREAKPOINT
$b = '4';
print "STEP " . &$a . " NOW\n";
$b = '5';
print "STEP " . &$a . " AGAIN\n";
Now, both test.pl
and its new shebang handler, perldbgcall.sh
, are in /tmp
; and we have nc
listening for debug connections on port 7234 - so we can finally open another terminal window, change directory to /tmp
, and run the one-liner webserver (which will listen for web connections on port 8080) there:
现在,测试。pl及其新的shebang处理程序perldbgcall。在/ tmp sh,;我们可以在7234端口上监听调试连接,这样我们就可以打开另一个终端窗口,将目录更改为/tmp,并运行一层的webserver(它将监听端口8080上的web连接):
cd /tmp
perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'
After this is done, we can go to our web browser, and request the same address, http://127.0.0.1:8080/test.pl
. However, now when the webserver tries to execute the script, it will do so through perldbgcall.sh
shebang - which will start perl
in remote debugger mode. Thus, the script execution will pause - and so the web browser will lock, waiting for data. We can now switch to the netcat
terminal, and we should see the familiar Perl debugger text - however, output through nc
:
完成之后,我们可以访问web浏览器,并请求相同的地址http://127.0.1:8080 /test.pl。但是,现在当webserver尝试执行脚本时,它将通过perldbgcall执行脚本。它将在远程调试器模式下启动perl。因此,脚本执行将暂停——因此web浏览器将锁定,等待数据。现在我们可以切换到netcat终端,我们应该可以看到熟悉的Perl调试器文本—但是,通过nc输出:
$ nc -l 7234
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(-e:1): do './test.pl'
DB<1> r
main::(./test.pl:29): $b = '4';
DB<1>
As the snippet shows, we now basically use nc
as a "terminal" - so we can type r
(and Enter) for "run" - and the script will run up do the breakpoint statement (see also In perl, what is the difference between $DB::single = 1 and 2?), before stopping again (note at that point, the browser will still lock).
片段显示,我们现在基本上使用数控作为“终端”——我们可以输入r(“运行”,并输入),脚本将断点声明(参见在perl,之间的区别是什么$ DB::单= 1和2 ?),再次停止前(注意在这一点上,浏览器仍然锁)。
So, now we can, say, step through the rest of test.pl
, through the nc
terminal:
所以,现在我们可以,比如说,逐步完成剩下的测试。pl,通过nc终端:
....
main::(./test.pl:29): $b = '4';
DB<1> n
main::(./test.pl:30): print "STEP " . &$a . " NOW\n";
DB<1> n
main::(./test.pl:31): $b = '5';
DB<1> n
main::(./test.pl:32): print "STEP " . &$a . " AGAIN\n";
DB<1> n
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1>
... however, also at this point, the browser locks and waits for data. Only after we exit the debugger with q
:
…然而,同样在这一点上,浏览器锁定并等待数据。只有当我们用q退出调试器后:
DB<1> q
$
... does the browser stop locking - and finally displays the (complete) output of test.pl
:
…浏览器是否停止锁定——并最终显示test.pl的(完整的)输出:
YEAH hello 2 there CMON
CMON hello 3 there YEAH
STEP hello 4 there NOW
STEP hello 5 there AGAIN
Of course, this kind of debug can be done even without running the web server - however, the neat thing here, is that we don't touch the web server at all; we trigger execution "natively" (for CGI) from a web browser - and the only change needed in the CGI script itself, is the change of shebang (and of course, the presence of the shebang wrapper script, as executable file in the same directory).
当然,这种调试可以在不运行web服务器的情况下完成——但是,这里最简单的一点是,我们根本不接触web服务器;我们从web浏览器触发执行“本机”(用于CGI)——以及CGI脚本本身所需要的唯一更改,是shebang的更改(当然,还有shebang包装器脚本的存在,作为同一个目录中的可执行文件)。
Well, hope this helps someone - I sure would have loved to have stumbled upon this, instead of writing it myself :)
Cheers!
好吧,希望这能对某人有所帮助——我当然希望自己无意中发现了这一点,而不是自己写下来:)干杯!
#5
4
For me, I use log4perl . It's quite useful and easy.
对于我来说,我使用log4perl。它很有用,也很简单。
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init( { level => $DEBUG, file => ">>d:\\tokyo.log" } );
my $logger = Log::Log4perl::get_logger();
$logger->debug("your log message");
#6
1
Honestly you can do all the fun stuff above this post. ALTHOUGH, the simplest and most proactive solution I found was to just "print it".
老实说,你可以在这篇文章上面做所有有趣的事情。虽然,我发现最简单和最积极的解决方案是“打印它”。
In example: (Normal code)
在示例:(正常代码)
`$somecommand`;
To see if it's doing what I really want it to do: (Trouble shooting)
看看它是否在做我真正想做的事情:(解决问题)
print "$somecommand";
#7
1
It will probably also be worth mentioning that Perl will always tell you on what line the error occurs when you execute the Perl script from the command line. (An SSH Session for example)
值得一提的是,当您从命令行执行Perl脚本时,Perl总是会告诉您错误发生在什么行。(例如SSH会话)
I will usually do this if all else fails. I will SSH into the server and manually execute the Perl script. For example:
如果其他都失败了,我通常会这样做。我将SSH到服务器并手动执行Perl脚本。例如:
% perl myscript.cgi
If there is a problem then Perl will tell you about it. This debugging method does away with any file permission related issues or web browser or web server issues.
如果有问题,那么Perl会告诉您。此调试方法消除与文件权限相关的任何问题或web浏览器或web服务器问题。
#8
0
You may run the perl cgi-script in terminal using the below command
您可以使用下面的命令在终端中运行perl cgi-script
$ perl filename.cgi
It interpret the code and provide result with HTML code .It will report the error if any.
它解释代码并提供HTML代码的结果,如果有错误,它将报告。