欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Apache 教程:使用 CGI 的动态内容 有大用

Apache 教程:使用 CGI 的动态内容


简介



相关模块相关指令
mod_alias
mod_cgi
mod_cgid
AddHandler
选项
ScriptAlias 指令

CGI(Common Gateway Interface)定义了一种 web 服务器与外部 content-generating 程序交互的方式,这些程序通常被称为 CGI 程序或 CGI 脚本。这是一种使用您最熟悉的编程语言将动态内容放在 web 网站上的简单方法。本文档将介绍如何在 Apache web 服务器上设置 CGI,并开始编写 CGI 程序。

配置 Apache 以允许 CGI

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

注意:如果已使用共享模块支持构建 Apache,则需要确保已加载模块;在你的httpd.conf中你需要确保LoadModule指令没有被注释掉。正确配置的指令可能如下所示:

LoadModule cgid_module modules/mod_cgid.so

在 Windows 上,或者像 prefork 一样使用 non-threaded MPM,正确配置的指令可能如下所示:

LoadModule cgi_module modules/mod_cgi.so

ScriptAlias

ScriptAlias 指令指令告诉 Apache 为 CGI 程序预留了一个特定的目录。 Apache 将假定此目录中的每个文件都是 CGI 程序,并且当 client 请求该特定资源时,将尝试执行它。

ScriptAlias 指令指令看起来像:

ScriptAlias "/cgi-bin/" "/usr/local/apache2/cgi-bin/"

如果您在默认位置安装了 Apache,则显示的 example 来自您的默认httpd.conf configuration 文件。 ScriptAlias 指令指令很像别号指令,它定义了一个映射到特定目录的 URL 前缀。 AliasScriptAlias通常用于DocumentRoot目录之外的目录。 AliasScriptAlias之间的区别在于ScriptAlias具有附加含义,即该 URL 前缀下的所有内容都将被视为 CGI 程序。因此,上面的 example 告诉 Apache,对于以/cgi-bin/开头的资源的任何请求都应该从目录/usr/local/apache2/cgi-bin/提供,并且应该被视为 CGI 程序。

例如,如果请求 URL http://www.example.com/cgi-bin/test.pl,Apache 将尝试执行文件/usr/local/apache2/cgi-bin/test.pl并_返回输出。当然,该文件必须以特定方式存在,并且可执行,并且 return 输出,或 Apache 将_return 错误消息。

CGI 在 ScriptAlias 目录之外

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

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

明确使用 Options 来允许 CGI 执行

您可以在主服务器 configuration 文件中明确使用选项指令来指定在特定目录中允许 CGI 执行:

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

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

AddHandler cgi-script .cgi .pl

.htaccess files

.htaccess 教程显示如果您无法访问httpd.conf,如何激活 CGI 程序。

用户目录

要允许在用户目录中以.cgi结尾的任何文件执行 CGI 程序,可以使用以下 configuration。

<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-type标头开头。这是 HTTP 标头,告诉 client 它接收的内容类型。大多数 time,这将看起来像:

Content-type: text/html

其次,您的输出需要使用 HTML 或浏览器能够显示的其他格式。大多数 time,这将是 HTML,但有时您可能会编写一个输出 gif 图像或其他 non-HTML 内容的 CGI 程序。

除了这两件事,编写 CGI 程序看起来很像你可能编写的任何其他程序。

您的第一个 CGI 计划

以下是一个 example CGI 程序,它将一个 line 打印到您的浏览器。键入以下内容,将其保存到名为first.pl的文件中,并将其放在cgi-bin目录中。

#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, World.";

即使您不熟悉 Perl,您也应该能够看到这里发生的事情。第一个 line 告诉 Apache(或者你恰好在 running 下运行的任何 shell),可以通过将文件提供给/usr/bin/perl位置找到的 interpreter 来执行该程序。第二个 line 打印我们所讨论的 content-type 声明,然后是两个 carriage-return 换行符对。这会在标题后面添加一个空白 line,以指示 HTTP headers 的结束和正文的开头。第三个 line 打印 string“Hello,World。”。这就是结束。

如果您打开自己喜欢的浏览器并告诉它获取地址

http://www.example.com/cgi-bin/first.pl

或者无论您将文件放在何处,您都会在浏览器窗口中看到一个 line Hello, World.。这不是很令人兴奋,但是一旦你开始工作,你将有机会获得任何有用的东西。

但它还没有用!

当您尝试从 web 访问 CGI 程序时,您可能会在浏览器中看到四个基本内容:

  • 您的 CGI 程序的输出
    大!这意味着一切正常。如果输出正确,但浏览器未正确处理,请确保在 CGI 程序中设置了正确的 Content-Type。

  • 您的 CGI 程序的 source code 或“POST Method Not Allowed”消息
    这意味着您尚未正确配置 Apache 来处理您的 CGI 程序。重新阅读有关配置 Apache 的部分,并尝试找到您错过的内容。

  • 以“禁止”开头的消息
    这意味着存在权限问题。检查 Apache 错误 log 以及下面有关文件权限的部分。

  • 显示“内部服务器错误”的消息
    如果您检查 Apache 错误 log,您可能会发现它显示“脚本 headers 的过早结束”,可能还有您的 CGI 程序生成的错误消息。在这种情况下,您需要检查以下每个部分,以查看可能阻止您的 CGI 程序发出正确的 HTTP headers 的原因。

文件权限

请记住,服务器不像你那样运行。也就是说,当服务器启动时,它会使用非特权用户的权限运行 - 通常是nobodywww - 因此它需要额外的权限来执行您拥有的 files。通常,为文件提供足够权限以便nobody执行的方法是为每个人提供对该文件的执行权限:

chmod a+x first.pl

此外,如果您的程序从任何其他 files 读取或写入,那些 files 将需要具有允许此权限的正确权限。

路径信息和环境

当您从命令 line 运行程序时,您有一些传递给 shell 的信息,而不用考虑它。对于 example,你有一个PATH,它告诉 shell 它可以在哪里找到你引用的 files。

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

这种常见的表现形式是 CGI 程序的第一个 line 中指示的脚本 interpreter(通常是perl)的路径,它看起来像:

#!/usr/bin/perl

确保这实际上是 interpreter 的路径。

在 Windows 上编辑 CGI 脚本时,end-of-line 字符可能会附加到 interpreter 路径。确保 files 然后以 ASCII 模式传输到服务器。如果不这样做可能会导致 OS 发出“命令未找到”警告,因为无法识别的 end-of-line 字符被解释为 interpreter 文件名的一部分。

缺少环境变量

如果您的 CGI 程序依赖于 non-standard 环境变量,则需要确保这些变量由 Apache 传递。

当您错过环境中的 HTTP headers 时,请确保它们的格式符合RFC 2616,section 4.2:标题名称必须以字母开头,后跟字母,numbers 或连字符。违反此规则的任何标头都将被静默删除。

程序错误

大多数 time 当 CGI 程序失败时,都是因为程序本身存在问题。一旦你掌握了这个 CGI 的东西,并且不再犯以上两个错误,这尤其是 true。首先要做的是确保程序在命令 line 之前运行,然后通过 web 服务器进行测试。对于 example,请尝试:

cd /usr/local/apache2/cgi-bin ./first.pl

(不要调用perl interpreter.shell 和 Apache 应该在 script.)的第一个 line 上使用路径信息找到 interpreter

您看到程序编写的第一件事应该是一组 HTTP headers,包括Content-Type,后跟一个空 line。如果您看到其他任何内容,Apache 将__ret 如果您尝试通过服务器运行错误。有关详细信息,请参阅上面的编写 CGI 程序。

错误日志

错误日志是你的朋友。出现任何错误都会在错误 log 中生成消息。你应该先看看那里。如果您托管 web 站点的地方不允许您访问错误 log,您可能应该在其他地方托管您的站点。学习阅读错误日志,您会发现几乎所有问题都能快速识别并快速解决。

Suexec

suEXEC支持程序允许 CGI 程序在不同的用户权限下运行,具体取决于它们所在的虚拟 host 或用户主目录.Suexec 具有非常严格的权限检查,并且该检查中的任何失败都将导致您的 CGI 程序失败Premature end of script headers

要检查您是否使用 suexec,run apachectl -V并检查SUEXEC_BIN的位置。如果 Apache 在启动时找到suEXEC二进制文件,则会激活 suexec。

除非你完全理解 suexec,否则你不应该使用它。要禁用 suexec,只需删除(或重命名)SUEXEC_BIN指向的suEXEC二进制文件,然后重新启动服务器。如果在阅读suEXEC之后,您仍然希望使用它,那么 run suexec -V找到 suexec log 文件的位置,并使用该 log 文件查找您违反的 policy。

幕后发生了什么?

随着您在 CGI 编程方面变得更加先进,了解更多有关幕后发生的事情将变得非常有用。具体来说,浏览器和服务器如何相互通信。因为虽然编写一个打印“Hello,World。”的程序非常好,但它并不是特别有用。

环境变量

环境变量是在您使用计算机时 float 周围的值。它们是非常有用的东西,例如您的路径(计算机在您键入时搜索实现命令的实际文件),用户名,终端类型等等。有关常规,每日环境变量的完整列表,请在命令提示符下键入env

在 CGI transaction 期间,服务器和浏览器还设置环境变量,以便它们可以相互通信。这些是浏览器类型(Netscape,IE,Lynx),服务器类型(Apache,IIS,WebSite),正在运行的 CGI 程序的 name 等等。

这些变量可供 CGI 程序员使用,并且是 client-server 通信故事的一半。所需变量的完整列表位于Common Gateway Interface RFC。

这个简单的 Perl CGI 程序将显示传递的所有环境变量。 Apache 发行版的cgi-bin目录中包含两个类似的程序。请注意,某些变量是必需的,而其他变量是可选的,因此您可能会看到列出的某些变量不在官方列表中。此外,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

服务器和 client 之间的其他通信通过标准输入(STDIN)和标准输出(STDOUT)进行。在正常的日常 context 中,STDIN表示键盘,或程序被赋予作用的文件,STDOUT通常表示 console 或屏幕。

当您bb 表单到 CGI 程序时,该表单中的数据被捆绑成一种特殊格式,并通过STDIN传递给您的 CGI 程序。然后,程序可以处理该数据,就好像它是从键盘或文件中传入的一样

“特殊格式”非常简单。字段 name 和它的 value 用等号(=)符号)连接在一起,并且用符号(&)连接在一起。空格,符号和等号等不方便的字符被转换为它们的十六进制等价物,以便它们不要搞砸了作品。整个数据 string 可能看起来像:

name=Rich%20Bowen&city=Lexington&state=KY&sidekick=Squirrel%20Monkey

您有时也会看到这种类型的 string 附加到 URL。完成后,服务器将该 string 放入名为QUERY_STRING的环境变量中。这被称为GET请求。您的 HTML 表单通过在FORM标记中设置METHOD属性来指定是使用GET还是POST来传递数据。

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

CGI modules/libraries

当您编写 CGI 程序时,您应该考虑使用 code library 或模块来为您完成大部分繁重的工作。这样可以减少错误,加快开发速度。

如果您在 Perl 中编写 CGI 程序,则可在CPAN上使用模块。最常用的模块是CGI.pm。您可能还会考虑CGI::Lite,它实现了一组最小的功能,这是大多数程序中所需要的。

如果你用 C 语言编写 CGI 程序,有很多选择。其中一个是来自http://www.boutell.com/cgic/CGIC library。

了解更多信息

当前的 CGI 规范可在Common Gateway Interface RFC中找到。

当您发布有关您正在使用的 CGI 问题的问题时,无论是邮件列表还是新闻组,请确保提供足够的信息,说明发生了什么,您希望发生什么,以及实际发生的情况有何不同,你正在运行什么服务器,你的 CGI 程序是什么语言,如果可能的话,还有令人讨厌的 code。这将使您更容易找到问题。

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


来自  https://www.docs4dev.com/docs/zh/apache/2.4/reference/howto-cgi.html


普通分类: