如何对 Perl CGI 脚本进行故障排除? [英] How can I troubleshoot my Perl CGI script?

查看:35
本文介绍了如何对 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 脚本的问题,最初出现在 Perlmonks 上作为 Perl CGI 脚本疑难解答.它不是每个人的完整指南您可能会遇到的问题,也没有关于错误压缩的教程.它这只是我二十年(加上!)年调试 CGI 脚本的经验的结晶.这个页面好像有很多不同的家,我好像忘记它的存在,所以我将它添加到 StackOverflow.你可以将任何意见或建议发送给我bdfoy@cpan.org.它也是社区维基,但不要太疯狂.:)

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 编译指示来强制自己始终清除有问题的代码:

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

 use warnings;

如果您需要比简短警告消息更多的信息,请使用 diagnostics pragma 获取更多信息,或查看 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 ";CGI.pm 及其衍生物,print header().某些服务器对出现在标准输出(在 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 "; 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 文件名.切勿将模式设置为 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 签出或其他不处理行尾翻译,网络服务器可能会看到您的脚本作为一大行.以 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 开关打开污点模式,这是一件好事,因为它可以让您将未经检查的数据传递给 shell.如果它抱怨它正在尽其职责帮助我们编写更安全的脚本.任何来自程序外部(即环境)的数据被认为是受污染的.环境变量,例如 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 合并如果您在终端上(例如交互式会话),以及由于缓冲可能会以混乱的顺序出现.打开Perl 的自动刷新功能通过将 $| 设置为真正的价值.通常你可能会看到 $|++;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_* 变量

设置这些变量

  • 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.pmCGI::Request,CGI::SimpleCGI::Lite,使用模块并继续生活.CGI.pm 有一个 cgi-lib.pl 兼容模式,可以帮你解决输入问题由于旧的 CGI 解析器实现而导致的问题.

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

说真的.有时我们会被问题所困扰,以至于我们发展知觉狭窄"(管视角).在休息,喝杯咖啡,或者在 [毁灭公爵、地震、毁灭战士、光环、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天全站免登陆