如何解决我的Perl CGI脚本问题? [英] How can I troubleshoot my Perl CGI script?

查看:83
本文介绍了如何解决我的Perl CGI脚本问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个不起作用的Perl脚本,而且我不知道如何开始缩小问题的范围.我该怎么办?

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?

注意:我添加这个问题是因为我真的很想在Stackoverflow中添加很长的答案.我在其他答案中始终保持外部链接,因此值得在这里.如果您要添加一些内容,请不要怕编辑我的答案.

Note: I'm adding the question because I really want to add my very lengthy answer to Stackoverflow. 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.

推荐答案

此答案旨在作为通过 Perl CGI脚本的问题,最初以对Perl CGI脚本进行故障排除的形式出现在Perlmonks上.并非每个人的完整指南 您可能会遇到的问题,也没有有关压缩漏洞的教程.它 仅仅是我调试CGI脚本二十年(加倍!)的经验的结晶.该页面似乎有很多不同的房屋,而且我似乎 忘记它的存在,所以我将其添加到StackOverflow中.你 可以通过以下方式向我发送任何意见或建议 bdfoy@cpan.org.它也是社区Wiki,但不要太过分. :)

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 twenty (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 StackOverflow. 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就代码中有问题的部分向您发出警告.您可以使用-w开关从命令行执行此操作,这样就不必更改任何代码或向每个文件添加编译指示:

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 program.pl

但是,您应该通过向所有文件中添加warnings pragma来强迫自己始终清除可疑代码:

However, you should force yourself to always clear up questionable code by adding the warnings pragma to all of your files:

 use warnings;

如果您需要除简短警告消息以外的更多信息,请使用diagnostics编译指示获取更多信息,或查看 perldiag 文档:

If you need more information than the short warning message, use the diagnostics pragma to get more information, or look in the perldiag documentation:

 use diagnostics;

您首先输出了有效的CGI标头吗?

服务器期望CGI脚本的第一个输出为CGI标头.通常情况下,它可能与print "Content-type: text/plain\n\n";一样简单,也可以使用 CGI.pm 及其衍生版本.某些服务器对在标准输出(在STDOUT上)之前出现的错误输出(在STDERR上)敏感.

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).

添加此行

 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.

服务器保留错误日志(或者至少应该保留). 来自服务器和脚本的错误输出应 出现在那儿.找到错误日志,然后查看错误内容. 日志文件没有标准位置.看在 服务器配置的位置,或询问服务器 行政.您还可以使用诸如 CGI :: Carp 之类的工具. 保留自己的日志文件.

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.

如果您看到诸如权限被拒绝"之类的错误,或方法不 已实施",则可能意味着您的脚本未 Web服务器用户可读和可执行.关于风味 在Unix上,建议将模式更改为755: chmod 755 filename.永远不要将模式设置为777!

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!

请记住,Perl在以下情况下会自动创建变量: 您首先使用它们.这是一个功能,但有时可以 如果您键入错误的变量名称,则会导致错误.语用 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.

您可以使用-c检查编译错误 转变.专注于报告的第一个错误.冲洗, 重复.如果您遇到了非常奇怪的错误,请检查 确保您的脚本的行尾正确.如果你 FTP以二进制模式,从CVS签出或其他方式 无法处理行尾翻译,Web服务器可能会看到 您的脚本是一大句.传输ASCII格式的Perl脚本 模式.

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.

如果您的脚本抱怨不安全的依赖关系,则您 可能正在使用-T开关打开异味模式,即 这是一件好事,因为它使您可以将未经检查的数据传递给外壳.如果 它抱怨它正在尽其所能来帮助我们编写更安全的脚本.任何 来自程序外部(即环境)的数据 被认为是污染的.环境变量,例如PATHLD_LIBRARY_PATH 尤其麻烦.您必须将它们设置为安全值 或按照我的建议完全取消设置它们.您应该使用绝对 无论如何.如果污点检查抱怨其他问题, 确保您未污染数据.请参见 perlsec 手册页以获取详细信息.

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.

脚本从命令行运行时是否输出您期望的结果 命令行?标头输出是第一个,后面是一个 空行?请记住,STDERR可以与STDOUT合并 如果您在终端上(例如互动会话),并且 由于缓冲可能会以混乱的顺序显示.打开 通过将$|设置为 真正的价值.通常,您可能会在 CGI程序.设置后,每次打印和写入 立即转到输出而不是被缓冲. 您必须为每个文件句柄设置此设置.使用select来 更改默认文件句柄,如下所示:

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:

$|++;                            #sets $| for STDOUT
$old_handle = select( STDERR );  #change to STDERR
$|++;                            #sets $| for STDERR
select( $old_handle );           #change back to STDOUT

无论哪种方式,第一件事输出都应该是CGI标头 后面跟一个空白行.

Either way, the first thing output should be the CGI header followed by a blank line.

Web服务器环境通常受限制得多 比您的命令行环境还多 有关请求的信息.如果您的脚本运行正常 从命令行,您可以尝试模拟Web服务器 环境.如果出现问题,则说明您有 环境问题.

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.

取消设置或删除这些变量

Unset or remove these variables

  • PATH
  • LD_LIBRARY_PATH
  • 所有ORACLE_*变量
  • PATH
  • LD_LIBRARY_PATH
  • all ORACLE_* variables

设置这些变量

  • REQUEST_METHOD(根据需要设置为GETHEADPOST)
  • SERVER_PORT(通常设置为80)
  • REMOTE_USER(如果您正在做受保护的访问工作)
  • REQUEST_METHOD (set to GET, HEAD, or POST as appropriate)
  • SERVER_PORT (set to 80, usually)
  • REMOTE_USER (if you are doing protected access stuff)

CGI.pm(> 2.75)的最新版本要求-debug标志用于 得到旧的(有用的)行为,因此您可能必须将其添加到 您的CGI.pm进口.

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.

use CGI qw(-debug)

您使用的是die()还是warn?

除非已重新定义,否则这些功能会打印到STDERR 他们.它们也不输出CGI标头.你可以得到 软件包具有相同的功能,例如 CGI :: Carp

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

如果您认为自己的脚本在做正确的事情,并且 当您手动执行请求时,您将获得正确的权限 输出,浏览器可能是罪魁祸首.清除缓存 并在测试时将缓存大小设置为零.请记住 一些浏览器确实很愚蠢,实际上不会重新加载 新内容,即使您告诉它这样做.这是 在URL路径为 相同,但是内容会发生变化(例如动态图片).

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).

脚本的文件系统路径不一定是 与脚本的URL路径直接相关.确保 您具有正确的目录,即使您必须编写一个 简短的测试脚本对此进行了测试.此外,您确定 您正在修改正确的文件?如果看不到 所做的任何更改,您可能正在修改 其他文件,或将文件上传到错误的位置. (顺便说一下,这是我最常见的此类麻烦原因 ;)

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 ;)

如果您的问题与解析CGI输入有关,并且您 没有使用经过广泛测试的模块,例如CGI.pm CGI::Request CGI::Simple

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.

如果使用以下命令运行外部命令 system,倒勾或其他IPC设施, 您应该使用外部程序的绝对路径. 您不仅确切地知道自己在运行什么,而且您 避免一些安全问题.如果你要开 用于读取或写入的文件,请使用绝对路径. CGI脚本可能对当前版本有不同的想法 目录比你做的多.或者,您可以执行 明确的chdir()将您放在正确的位置.

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.

大多数Perl函数会告诉您它们是否起作用 并在失败时设置$!.你检查了吗 返回值并检查$!是否有错误消息?你检查了吗 $@,如果您使用的是eval?

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的最新稳定版本是5.28(或不是,取决于上次编辑的时间).您使用的是旧版本吗?不同版本的Perl可能会有不同的警告概念.

The latest stable version of Perl is 5.28 (or not, depending on when this was last edited). Are you using an older version? Different versions of Perl may have different ideas of warnings.

不同的服务器在同一服务器上的行为可能有所不同 情况.相同的服务器产品在以下方面可能会有所不同 不同的配置.包括尽可能多的 您可以在任何请求帮助中获得的信息.

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.

认真的CGI程序员应该对 尽可能的服务器-不仅包括服务器功能 和行为,还有本地配置.这 您的服务器文档可能不可用 如果您使用的是商业产品.否则, 文档应该在您的服务器上.如果不是,请看 在网络上.

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.

此用法很有用,但所有好的海报都已死亡或徘徊.

很可能以前有人遇到过您的问题, 并且有人(可能是我)已经回答了这个问题 新闻组.尽管该新闻组已经过了鼎盛时期,但从过去收集来的智慧有时还是有用的.

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.

在大型系统中,可能难以跟踪错误 因为发生了很多事情.尝试重现问题 使用最短脚本的行为.知道问题 是大多数修复程序.这可能很耗时,但是您 尚未发现问题,并且您的选件已用完. :)

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. :)

严重.有时我们会陷入困境,以至于我们 发展知觉变窄" (管视角).在休息, 喝一杯咖啡,或在[杜克·努克(Duke Nukem),雷神之锤(Doke),晕圈(Halo),化学需氧量(COD)]中炸死一些坏人 您需要重新解决问题的崭新视角.

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.

再次严重.有时大声解释问题 引导我们找到自己的答案.与企鹅交谈(毛绒玩具),因为 您的同事不在听.如果您对此感兴趣 作为一种严肃的调试工具(如果您还没有的话,我建议您使用它 现已发现问题),您可能还想阅读心理学 程序设计.

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.

这篇关于如何解决我的Perl CGI脚本问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆