• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 使用CGI的动态内容

    配置Apache以允许CGI

    为了使您的CGI程序正常运行,您需要将Apache配置为允许CGI执行。有几种方法可以做到这一点。

    注意:如果Apache是使用共享模块支持构建的,则需要确保已加载该模块;否则,请确保已加载。在您中,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和之间的区别ScriptAliasScriptAlias具有附加的含义,即该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

    ScriptAlias出于安全原因,CGI程序通常仅限于ed目录。这样,管理员可以严格控制允许谁使用CGI程序。但是,如果采取了适当的安全预防措施,则没有理由不能从任意目录运行CGI程序。例如,您可能希望使用UserDir指令让用户在其主目录中拥有Web内容。如果他们想拥有自己的CGI程序,但无权访问主cgi-bin目录,则他们将需要能够在其他地方运行CGI程序。

    允许在任意目录中执行CGI有两个步骤。首先,cgi-script必须使用AddHandlerSetHandler指令激活处理程序。其次,ExecCGI必须在Options指令中指定。

    明确使用选项来允许CGI执行

    您可以Options在主服务器配置文件中显式使用指令,以指定允许在特定目录中执行CGI:

    <Directory "/usr/local/apache2/htdocs/somedir">
        Options +ExecCGI
    </Directory>
    

    上面的指令告诉Apache允许执行CGI文件。您还需要告诉服务器哪些文件是CGI文件。以下AddHandler指令告诉服务器将带有cgipl扩展名的所有文件视为CGI程序:

    AddHandler cgi-script .cgi .pl
    

    htaccess文件

    .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编程之间有两个主要区别。

    首先,您CGI程序的所有输出必须在MIME类型标头之前。这是HTTP标头,告诉客户端它正在接收哪种内容。大多数时候,这看起来像:

    Content-type: text/html
    

    其次,您的输出必须采用HTML或浏览器将能够显示的其他格式。在大多数情况下,这将是HTML,但有时您可能会编写一个CGI程序来输出gif图像或其他非HTML内容。

    除了这两点之外,编写CGI程序看起来与您可能编写的任何其他程序非常相似。

    您的第一个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程序时,可能会在浏览器中看到以下四个基本信息:

    您的CGI程序的输出
    大!这意味着一切正常。如果输出正确,但是浏览器未正确处理,请确保您Content-Type的CGI程序中设置正确。
    CGI程序的源代码或“不允许使用POST方法”消息
    这意味着您没有正确配置Apache以处理您的CGI程序。重读有关配置Apache的部分,然后尝试查找您错过的内容。
    以“禁止”开头的消息
    这意味着存在权限问题。检查 Apache错误日志和下面有关文件权限的部分。
    一条消息,指出“内部服务器错误”
    如果检查 Apache错误日志,则可能会发现它显示“脚本头过早结束”,可能还会显示CGI程序生成的错误消息。在这种情况下,您将需要检查以下每个部分,以查看可能阻止CGI程序发出正确的HTTP标头的原因。

    档案权限

    请记住,服务器不会像您那样运行。也就是说,服务器启动时,将以无特权用户的权限(通常是nobodywww)运行,因此它将需要额外的权限才能执行您拥有的文件。通常,授予文件足够的nobody执行权限的方法是向所有人授予对该文件的执行权限:

    chmod a+x first.pl
    

    同样,如果您的程序读取或写入任何其他文件,则这些文件将需要具有正确的权限才能允许这样做。

    路径信息和环境

    从命令行运行程序时,无需考虑即可将某些信息传递到外壳。例如,您有一个PATH,告诉外壳程序可以在哪里查找您引用的文件。

    当程序作为CGI程序通过Web服务器运行时,它可能没有相同的PATH。您在CGI程序中调用的任何程序(sendmail例如)都需要由完整路径指定,以便外壳程序在尝试执行CGI程序时可以找到它们。

    一个常见的体现是perlCGI程序第一行中指示的脚本解释器的路径(通常是),看起来像这样:

    #!/ usr / bin / perl
    

    确保实际上这是解释器的路径。

    在Windows上编辑CGI脚本时,行尾字符可能会附加到解释器路径中。确保随后将文件以ASCII模式传输到服务器。否则,由于无法识别的行尾字符将被解释为解释器文件名的一部分,因此可能会导致操作系统发出“找不到命令”警告。

    缺少环境变量

    如果您的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)进行。在正常的日常情况下,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来传递数据。METHODFORM

    然后,您的程序负责将字符串拆分成有用的信息。幸运的是,有一些库和模块可用来帮助您处理这些数据以及处理CGI程序的其他方面。

    CGI模块/库

    编写CGI程序时,应考虑使用代码库或模块来完成大部分繁琐的工作。这样可以减少错误,加快开发速度。

    如果您在Perl中编写CGI程序,则可以在CPAN上使用模块。为此,最受欢迎的模块是CGI.pm。您可能还考虑了CGI::Lite,它实现了最少的功能集,这是大多数程序中所需要的。

    如果您使用C编写CGI程序,则有多种选择。其中之一是CGIC来自http://www.boutell.com/cgic/的图书馆。

    了解更多信息

    当前的CGI规范在通用网关接口RFC中可用。

    当您将有关CGI问题的问题发布到邮件列表或新闻组时,请确保您提供了有关发生了什么,预期发生了什么以及实际发生了什么不同的足够信息,您正在运行的服务器,CGI程序所使用的语言以及(如果可能)令人讨厌的代码。这将使查找问题变得更加简单。

    请注意,除非您确定在Apache源代码中发现了问题,否则有关CGI问题的问题绝不应发布到Apache错误数据库中。