相关模块 | 相关指令 |
---|---|
CGI(通用网关接口)为Web服务器定义了一种与外部内容生成程序进行交互的方式,这些程序通常称为CGI程序或CGI脚本。这是一种使用最熟悉的编程语言将动态内容放置在您的网站上的简单方法。本文档将介绍如何在Apache Web服务器上设置CGI,以及如何开始编写CGI程序。
为了使您的CGI程序正常工作,您需要将Apache配置为允许CGI执行。有几种方法可以做到这一点。
httpd.conf
您需要确保该
LoadModule
指令未被注释掉。正确配置的指令可能如下所示:
LoadModule cgid_module modules/mod_cgid.so在Windows上,或使用非线程MPM(例如prefork),正确配置的指令可能如下所示:
LoadModule cgi_module modules/mod_cgi.so
该
ScriptAlias
指令告诉Apache已为CGI程序保留了一个特定目录。Apache将假定此目录中的每个文件都是CGI程序,并在客户端请求该特定资源时尝试执行该文件。
该ScriptAlias
指令如下所示:
ScriptAlias "/cgi-bin/" "/usr/local/apache2/cgi-bin/"
httpd.conf
如果将Apache安装在默认位置,则显示的示例来自默认配置文件。该ScriptAlias
指令是很像的Alias
指令,它定义了一个URL前缀,映射到一个特定的目录。Alias
并且ScriptAlias
通常用于目录之外的DocumentRoot
目录。Alias
和之间的区别
ScriptAlias
是ScriptAlias
具有附加的含义,即该URL前缀下的所有内容都将被视为CGI程序。因此,上面的示例告诉Apache /cgi-bin/
对目录开头的任何资源请求都应从目录中提供 /usr/local/apache2/cgi-bin/
,并且应将其视为CGI程序。
例如,如果http://www.example.com/cgi-bin/test.pl
请求URL
,Apache将尝试执行该文件
/usr/local/apache2/cgi-bin/test.pl
并返回输出。当然,该文件必须存在并且可以执行,并以特定方式返回输出,否则Apache将返回错误消息。
ScriptAlias
出于安全原因,CGI程序通常仅限于ed目录。这样,管理员可以严格控制允许谁使用CGI程序。但是,如果采取了适当的安全预防措施,则没有理由不能从任意目录运行CGI程序。例如,您可能希望使用UserDir
指令让用户在其主目录中拥有Web内容
。如果他们想拥有自己的CGI程序,但无权访问主cgi-bin
目录,则他们将需要能够在其他地方运行CGI程序。
允许在任意目录中执行CGI有两个步骤。首先,cgi-script
必须使用AddHandler
或SetHandler
指令激活处理程序。其次,
ExecCGI
必须在Options
指令中指定。
您可以Options
在主服务器配置文件中显式使用指令,以指定允许在特定目录中执行CGI:
<Directory "/usr/local/apache2/htdocs/somedir"> Options +ExecCGI </Directory>
上面的指令告诉Apache允许执行CGI文件。您还需要告诉服务器哪些文件是CGI文件。以下AddHandler
指令告诉服务器将带有cgi
或pl
扩展名的所有文件视为CGI程序:
AddHandler cgi-script .cgi .pl
本.htaccess
教程
显示了如果您无权访问,如何激活CGI程序httpd.conf
。
要允许.cgi
以用户目录结尾的任何文件执行CGI程序
,可以使用以下配置。
<Directory "/home/*/public_html"> Options +ExecCGI AddHandler cgi-script .cgi </Directory>
如果希望cgi-bin
在用户目录的子目录中指定所有内容都将被视为CGI程序,则可以使用以下命令。
<Directory "/home/*/public_html/cgi-bin"> Options ExecCGI SetHandler cgi-script </Directory>
``常规''编程和CGI编程之间有两个主要区别。
首先,您CGI程序的所有输出必须在MIME类型标头之前。这是HTTP标头,告诉客户端它正在接收哪种内容。大多数时候,这看起来像:
Content-type: text/html
其次,您的输出必须为HTML或浏览器将能够显示的其他格式。在大多数情况下,这将是HTML,但有时您可能会编写一个CGI程序来输出gif图像或其他非HTML内容。
除了这两点之外,编写CGI程序看起来与您可能编写的任何其他程序非常相似。
以下是一个示例CGI程序,该程序将一行输出到您的浏览器。输入以下内容,将其保存到名为的文件中first.pl
,并将其放在
cgi-bin
目录中。
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "Hello, World.";
即使您不熟悉Perl,您也应该能够看到这里发生的情况。第一行告诉Apache(或您碰巧在其下运行的任何Shell),可以通过将文件提供给location中的解释器来执行该程序/usr/bin/perl
。第二行显示我们所讨论的内容类型声明,其后是两个回车换行符。这会在标头之后放置一个空白行,以指示HTTP标头的结尾和正文的开头。第三行显示字符串“ Hello,World”。到此为止。
如果您打开喜欢的浏览器并告诉它获取地址
http://www.example.com/cgi-bin/first.pl
或将文件放在任何位置,都会Hello, World.
在浏览器窗口中看到一行
。这不是很令人兴奋,但是一旦您能够正常工作,您就有很大的机会让几乎所有的东西都能正常工作。
当您尝试从网络访问CGI程序时,可能会在浏览器中看到以下四个基本信息:
Content-Type
的CGI程序中设置正确。请记住,服务器不会像您那样运行。也就是说,当服务器启动时,它正在以无特权用户的权限(通常是nobody
或
www
)运行,因此它将需要额外的权限才能执行您拥有的文件。通常,授予文件足够的nobody
执行权限的方法是向所有人授予对该文件的执行权限:
chmod a+x first.pl
同样,如果您的程序读取或写入任何其他文件,则这些文件将需要具有正确的权限才能允许这样做。
当您从命令行运行程序时,无需考虑就可以将某些信息传递给外壳。例如,您有一个PATH
,告诉外壳程序可以在哪里查找您引用的文件。
当程序作为CGI程序通过Web服务器运行时,它可能没有相同的PATH
。您在CGI程序中调用的任何程序(sendmail
例如)都需要用完整路径指定,以便外壳程序在尝试执行CGI程序时可以找到它们。
一个常见的体现是perl
CGI程序第一行中指示的脚本解释器的路径(通常是),看起来像这样:
#!/usr/bin/perl
确保实际上这是解释器的路径。
如果您的CGI程序依赖于非标准环境变量,则需要确保这些变量由Apache传递。
当您错过环境中的HTTP标头时,请确保它们按照RFC 2616第4.2节的格式设置 :标头名称必须以字母开头,然后只能是字母,数字或连字符。任何违反此规则的标头都将被静默删除。
大多数时候,CGI程序失败是由于程序本身存在问题。一旦掌握了CGI的知识,并且不再犯上述两个错误,就尤其如此。首先要做的是确保在通过Web服务器测试程序之前,从命令行运行程序。例如,尝试:
cd /usr/local/apache2/cgi-bin
./first.pl
(不要调用perl
解释器。shell和Apache应该使用脚本第一行中的路径信息来找到解释器。)
您看到的由程序编写的第一件事应该是一组HTTP标头,包括Content-Type
,后跟一个空行。如果您看到其他任何内容,Premature end of script headers
如果尝试通过服务器运行它,Apache将返回错误。有关更多详细信息,请参见上面的编写CGI程序。
错误日志是您的朋友。发生任何错误都会在错误日志中生成消息。您应该始终先查看那里。如果您托管网站的位置不允许您访问错误日志,则可能应该将网站托管在其他位置。学习阅读错误日志,您会发现几乎所有问题都得到了快速识别和快速解决。
该suexec的支持程序允许CGI程序在不同的用户权限运行,这取决于虚拟主机或用户主目录它们位于英寸的SuExec有非常严格的权限检查,并在检查任何失败将导致你的CGI程序与失败Premature end of script headers
。
要检查您是否正在使用suexec,请运行apachectl
-V
并检查的位置SUEXEC_BIN
。如果Apache suexec
在启动时在其中找到二进制文件,则suexec将被激活。
除非您完全了解suexec,否则不应该使用它。要禁用suexec,只需删除(或重命名)suexec
指向的二进制文件SUEXEC_BIN
,然后重新启动服务器即可。如果在阅读完suexec之后,您仍然希望使用它,请运行suexec -V
以查找suexec日志文件的位置,然后使用该日志文件查找您违反的策略。
随着CGI编程的发展,您将对了解幕后发生的事情变得很有用。具体来说,浏览器和服务器之间如何通信。因为尽管编写一个打印“ Hello,World。”的程序非常好,但是它并不是特别有用。
环境变量是在您使用计算机时在您周围浮动的值。它们非常有用,例如您的路径(在计算机上键入命令时,计算机会在其中搜索实际的文件以执行命令),用户名,终端类型等。有关日常的日常环境变量的完整列表,请
env
在命令提示符下键入。
在CGI事务期间,服务器和浏览器还会设置环境变量,以便它们可以相互通信。这些是浏览器类型(Netscape,IE,Lynx),服务器类型(Apache,IIS,WebSite),正在运行的CGI程序的名称等。
这些变量可供CGI程序员使用,并且只是客户端与服务器之间通讯的一半。所需变量的完整列表位于 Common Gateway Interface RFC。
这个简单的Perl CGI程序将显示所有正在传递的环境变量。cgi-bin
Apache发行版的目录中包含两个类似的程序
。请注意,某些变量是必需的,而其他变量是可选的,因此您可能会看到其中列出的一些不在正式列表中的变量。此外,Apache提供了许多不同的方法来
将您自己的环境变量添加
到默认提供的基本变量中。
#!/usr/bin/perl use strict; use warnings; print "Content-type: text/html\n\n"; foreach my $key (keys %ENV) { print "$key --> $ENV{$key}<br>"; }
服务器和客户端之间的其他通信通过标准输入(STDIN
)和标准输出(STDOUT
)进行。在正常的日常情况下,
STDIN
是指键盘或程序被赋予作用的文件,STDOUT
通常是指控制台或屏幕。
当您POST
将Web表单连接到CGI程序时,该表单中的数据将捆绑成一种特殊格式,并通过传递给您的CGI程序STDIN
。然后,程序可以像处理来自键盘或文件的数据一样处理该数据。
“特殊格式”非常简单。字段名称及其值用等号(=)连接在一起,而值对用&符(&)连接在一起。不方便的字符(例如空格,&符和等号)将转换为等效的十六进制,以免影响作品的质量。整个数据字符串可能类似于:
name=Rich%20Bowen&city=Lexington&state=KY&sidekick=Squirrel%20Monkey
有时您还会看到将这种类型的字符串附加到URL。完成后,服务器将该字符串放入名为的环境变量中
QUERY_STRING
。这就是所谓的GET
请求。您的HTML表单通过在标记中设置属性来指定是使用a GET
还是a POST
来传递数据
。METHOD
FORM
然后,您的程序负责将该字符串拆分为有用的信息。幸运的是,有一些库和模块可用来帮助您处理这些数据以及处理CGI程序的其他方面。
编写CGI程序时,应考虑使用代码库或模块来完成大部分繁琐的工作。这样可以减少错误,加快开发速度。
如果您在Perl中编写CGI程序,则可以在CPAN上使用模块。为此,最受欢迎的模块是CGI.pm
。您可能还会考虑CGI::Lite
,它实现了最少的功能集,这是大多数程序中所需要的。
如果您使用C编写CGI程序,则有多种选择。其中之一是CGIC
图书馆,网址为
http://www.boutell.com/cgic/。
当前的CGI规范在通用网关接口RFC中可用 。
当您将有关CGI问题的问题发布到邮件列表或新闻组时,请确保您提供了有关发生的事情,预期发生的事情以及实际发生的事情有何不同的足够信息,您正在运行的服务器,CGI程序所使用的语言以及(如果可能)有问题的代码。这将使查找问题变得更加简单。
请注意, 除非您确定在Apache源代码中发现了问题,否则切勿将有关CGI问题的问题发布到Apache错误数据库中。