概要

相关模块 相关指令

CGI(公共网关接口[Common Gateway Interface])定义了网站服务器与外部内容协商程序之间交互的方法,通常是指CGI程序或者CGI脚本,是在网站上实现动态页面的最简单而常用的方法。本文将对如何在Apache网站服务器上建立CGI以及如何编写CGI程序作介绍。

配置Apache以允许CGI

要让CGI程序能正常运作,必须配置Apache以允许CGI的执行,其方法有多种。

ScriptAlias

ScriptAlias指令使Apache允许执行一个特定目录中的CGI程序。当客户端请求此特定目录中的资源时,Apache假定其中文件都是CGI程序并试图运行。

ScriptAlias指令形如:

ScriptAlias /cgi-bin/ /usr/local/apache/cgi-bin/

如果Apache被安装到默认的位置,默认的配置文件httpd.conf中则会有上述配置。ScriptAlias指令定义了映射到一个特定目录的URL前缀,与Alias指令非常相似,两者一般都用于指定位于DocumentRoot目录以外的目录,其区别是ScriptAlias又多了一层含义,即其URL前缀中任何文件都被视为CGI程序。所以,上述例子会指示Apache,/cgi-bin/应该指向/usr/local/apache/cgi-bin/目录,且视之为CGI程序。

举例,如果有URL为http://www.example.com/cgi-bin/test.pl的请求,Apache会试图执行/usr/local/apache/cgi-bin/test.pl文件并返回其输出。当然,这个文件必须存在而且可执行,并以特定的方法产生输出,否则Apache返回一个出错消息。

ScriptAlias目录以外的CGI

由于安全原因,CGI程序通常被限制在ScriptAlias指定的目录中,如此,管理员就可以严格地控制谁可以使用CGI程序。但是,如果采取了恰当的安全方法措施,则没有理由不允许其他目录中的CGI程序运行。比如,你可能希望用户在UserDir指定的宿主目录中存放页面,而他们有自己的CGI程序,但无权存取cgi-bin目录,这样,就产生了运行其他目录中CGI程序的需求。

用Options显式地允许CGI的执行

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

<Directory /usr/local/apache/htdocs/somedir> 
Options +ExecCGI
</Directory>

上述指令使Apache允许CGI文件的执行。另外,还必须告诉服务器哪些文件是CGI文件。下面的AddHandler指令告诉服务器所有带有cgipl后缀的文件是CGI程序:

AddHandler cgi-script cgi pl

.htaccess文件

.htaccess文件是针对目录进行配置的一种方法。Apache在提供一个资源时,会在此资源所在目录中寻找.htaccess文件,如果有,则使其中的指令生效。AllowOverride 指令决定了.htaccess文件是否有效,它指定了哪些指令可以出现在其中,或者根本不允许使用。为此,需要在主服务器配置中如此配置:

AllowOverride Options

.htaccess文件中,需要如此配置:

Options +ExecCGI

以使Apache允许此目录中CGI程序的执行。

编写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这个文件可以用/usr/bin/perl(或者任何你正在使用的shell)解释并执行。第二行,打印上述要求的内容类型说明,并带有两个换行,在头后面留出空行,以示HTTP头的结束。第三行,打印文字``Hello, World.''。程序到此结束。

打开你喜欢的浏览器并输入地址:

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

或者是你存放程序的其他位置,就可以在浏览器窗口中看到一行Hello, World.。虽然并不怎么激动人心,但是一旦这个程序能正常运作,那么就可能运作其他任何程序。

程序还是不能运行!

从网络访问CGI程序,浏览器中可能会发生四种情况:

CGI程序的输出
太好了!这说明一切正常。
CGI程序的源代码或者一个"POST Method Not Allowed"消息
这说明Apache没有被正确配置以执行CGI程序,重新阅读configuring Apache看看遗漏了什么。
一个以"Forbidden"开头的消息
这说明有权限问题。参考Apache error log和下面的文件的权限
一个"Internal Server Error"消息
查阅Apache error log,可以找到CGI程序产生的出错消息"Premature end of script headers"。对此,需要检查下列各项,以找出不能产生正确HTTP头的原因。

文件的权限

记住,服务器不是以你的用户身份运行的,就是说,在服务器启动后,拥有的是一个非特权用户的权限-通常是``nobody''或者``www'' -而需要更大的权限以允许文件的执行。通常,给予``nobody''足够的权限以执行文件的方法是,对文件赋予everyone execute权限:

chmod a+x first.pl

另外,如果需要对其他文件进行读取或写入,也必须对这些文件赋予正确的权限。

如果服务器被配置为使用suexec则是一个例外。这个程序允许CGI程序根据其所在虚拟主机或用户宿主目录的不同而以不同的用户权限运行。Suexec有极其严格的权限校验,任何校验失败都会使CGI程序运行失败而产生"Internal Server Error"。对此,需要检查suexec的日志文件以发现哪个安全校验出问题了。

路径信息

当你在命令行执行一个程序,某些信息会自动传给shell而无须你操心,比如一个路径,告诉shell你所引用的文件可以在哪儿找到。

但是,在CGI程序通过网站服务器执行时,则没有此路径,所以,你在CGI程序中引用的任何程序(如sendmail)都必须指定其完整的路径,使shell能找到它们以执行你的CGI程序。

一种普通的用法是,在CGI程序的第一行中指明解释器(通常是perl),形如:

#!/usr/bin/perl

必须保证它的确指向解释器。

语法错误

多数CGI程序失败的原因在于程序本身有问题,尤其是在已经消除上述两种错误而CGI挂起的情况下。在用浏览器测试以前,先在命令行中执行你的程序,能够发现大多数的问题。

出错记录

出错记录是你的朋友。任何错误都会在出错记录中有记载,所以你应该首先查看它。如果你的网站空间提供者不允许访问出错记录,那么你应该考虑换一个空间提供者。学会阅读出错记录,可以快速找出问题并快速解决。

幕后是怎样操作的?

当你的CGI编程逐渐深入,理解幕后的操作,尤其是浏览器和服务器如何与其他的通讯,就变得有用了。虽然成功地写了一个程序打印``Hello, World.'',但并没有实际的用处。

环境变量

环境变量是使用计算机时到处都会用到的变量,比如路径(对实际文件的一个搜索路径以补全你的输入)、你的用户名以及你的终端类型等等。在命令行输入env,可以得到你的标准的当天的环境变量列表。

在CGI处理过程中,服务器和浏览器都会设置环境变量,比如浏览器类型(Netscape, IE, Lynx)、服务器类型(Apache, IIS, WebSite)以及将要执行的CGI程序名称等等。

所有这些变量对CGI程序员都有效,但只是客户端-服务器通讯的一半内容。完整的变量列表见http://hoohoo.ncsa.uiuc.edu/cgi/env.html

这个简单的CGI程序列出了环境中所有的环境变量,Apache发行版的cgi-bin中还有两个类似的程序。注意,有些变量是必须的,有些则是可选的,所以你可能会看见一些官方列表中没有的变量。另外,Apache提供了多种不同方法以在默认提供的变量中增加你的专用环境变量

#!/usr/bin/perl
print "Content-type: text/html\n\n";
foreach $key (keys %ENV) {
print "$key --> $ENV{$key}<br>";
}

STDIN和STDOUT

服务器和客户端之间的其他通讯都通过标准输入设备(STDIN)和标准输出设备(STDOUT)完成。通常,STDIN是指键盘或者一个程序所作用于的一个文件,STDOUT指控制台或显示器。

当你POST一个网络表格到一个CGI程序时,表格中的数据被捆扎为一个特殊形式通过STDIN传送给CGI程序,这样,这个程序就可以处理这些数据,仿佛这些数据来自键盘或者一个文件。

这种``特殊形式''很简单,一个字段名称及其值,中间用等号(=)连接,多个这样的字段对用与符号(&)连接。非常规字符,如空格、与符号和等号,被转换为其等值的十六进制以免出问题。整个字串形如:

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

有时,你会发现URL后面缀有这样的字串。这种形式会使服务器以这个字串的内容设置环境变量QUERY_STRING,称为GET请求。你的HTML表格在FORM标记中设置METHOD属性,以指定传送数据的行为使GET或者是POST

接着,你的程序必须把这个字串分离以获得有用的信息。所幸,有库和模块可以帮助你处理这些数据,还有为你的CGI程序达成其他目的的处理器。

CGI模块/库

编写CGI程序时,你应该考虑使用代码库或模块来完成多数琐碎的工作,以减少错误并更快地开发。

如果用Perl语言编写CGI程序,可用的模块见CPAN,最常用的模块是CGI.pm。也可以考虑用CGI::Lite,它实现了一个在多数程序中所有必须的最小功能集

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

更多资料

网上有大量的CGI资源。可以在Usenet组comp.infosystems.www.authoring.cgi和别人讨论CGI相关问题。HTML Writers Guild的-servers邮件列表是一个优秀的问题解答资源。更多资源可以在http://www.hwg.org/lists/hwg-servers/找到。

另外,还可以阅读CGI规范,其中有CGI程序操作的所有细节,原始版本见NCSA,另有一个更新草案见Common Gateway Interface RFC project

当你向一个邮件列表或者新闻组提交CGI相关问题时,你应该确保提供了足够的信息以更简单地发现并解决问题,诸如:发生了什么事、你希望得到什么结果、结果与你所期望的有什么出入、你运行的服务器、CGI程序是用什么语言编写的、如果可能就提供那个讨厌的代码。

注意,绝不要把CGI相关问题提交到Apache bug database,除非你坚信发现的是Apache源代码中的问题。

Apache指南:CGI动态页面的更多相关文章

  1. rhel7+apache+c cgi+动态域名实现web访问

    1. 申请动态域名/安装no-ip客户端 https://blog.csdn.net/lee244868149/article/details/44095835 2. yum安装httpd 两种方法安 ...

  2. [Apache手册]Linux环境下配置Apache运行cgi

    CGI动态页面 相关模块 相关指令 mod_alias mod_cgi AddHandler Options ScriptAlias CGI(公共网关接口)定义了web服务器与外部内容生成程序之间交互 ...

  3. CGI实现页面的动态生成

    传统的Web应用开发局限于有限的静态页面(HTML静态页面),不利于系统的扩展,不能提供及时信息,而且修改维护麻烦,所以建立一个动态Web应用程序尤为重要.一方面根据访问者的不同请求返回不同的访问信息 ...

  4. Spring MVC 学习总结(七)——FreeMarker模板引擎与动态页面静态化

    模板引擎可以让程序实现界面与数据分离,业务代码与逻辑代码的分离,这就提升了开发效率,良好的设计也使得代码复用变得更加容易.一般的模板引擎都包含一个模板解析器和一套标记语言,好的模板引擎有简洁的语法规则 ...

  5. socket用法以及tomcat静态动态页面的加载

    一.套接字的使用: 分为以下几步: 1.创建ServerSocket 2.接收客户端的连接 3.读取本地的test.html文件 4.构建数据输出通道 5.发送数据 6.关闭资源 代码参考: pack ...

  6. 动态页面技术JSP/EL/JSTL

    本节内容: jsp脚本和注释 jsp运行原理 jsp指令(3个) jsp内置/隐式对象(9个) jsp标签(动作) EL技术 JSTL技术 JavaEE的开发模式 动态页面技术:就是在html中嵌入j ...

  7. STRUTS2配置动态页面

      STRUTS2配置动态页面 CreateTime--2017年5月11日09:00:31Author:Marydon 1.struts配置 <?xml version="1.0&q ...

  8. JavaEE之动态页面技术(JSP/EL/JSTL)

    动态页面技术(JSP/EL/JSTL) JSP技术 jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%= ...

  9. 配置apache运行cgi程序

    配置apache运行cgi程序 文章目录 [隐藏] ScriptAlias目录的CGI ScriptAlias目录以外的CGI 配置apache运行cgi程序可分为两种情况,一是ScriptAlias ...

随机推荐

  1. EasyUI 扩展自己定义EasyUI校验规则 验证规则(经常使用的)

    比如 校验输入框仅仅能录入0-1000之间 最多有2位小数的数字 表单<input type="text" id="rate" name="ra ...

  2. Java串口通信详细解释

    前言 说到开源.恐怕非常少有人不挑大指称赞. 学生通过开源码学到了知识,程序猿通过开源类库获得了别人的成功经验及可以按时完毕手头的project,商家通过开源软件赚到了钱……,总之是皆大欢喜. 然而开 ...

  3. HDU 3376 &amp;&amp; 2686 方格取数 最大和 费用流裸题

    题意: 1.一个人从[1,1] ->[n,n] ->[1,1] 2.仅仅能走最短路 3.走过的点不能再走 问最大和. 对每一个点拆点限流为1就可以满足3. 费用流流量为2满足1 最大费用流 ...

  4. CSharp设计模式读书笔记(21):状态模式(学习难度:★★★☆☆,使用频率:★★★☆☆)

    模式角色与结构: 示例代码:(本示例在具体状态类中实现状态切换,也可以在环境类中实现状态切换.状态模式一定程度上违背开闭原则) using System; using System.Collectio ...

  5. CSharp设计模式读书笔记(9):组合模式(学习难度:★★★☆☆,使用频率:★★★★☆)

    组合模式(Composite Pattern): 组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构.组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可 ...

  6. Ajax得知(两)—— 一个简单的Ajax示例

    通过部分博客认识Ajax之后,我们通过一个简单的实例来消化消化理论知识,一睹Ajax的庐山真面目. 1.实例功能: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZ ...

  7. crm创建和编辑全局选项集

    一个选项集就是可包含在一个实体中的某种类型的字段.它定义一组选项.当一个选项集显示在窗口中时,将使用下拉列表控件.当在 Advanced Find 中显示时,则使用选择列表控件.有时,开发者将选项集称 ...

  8. 关于linux 原始套接字编程

    关于linux 网络编程最权威的书是<<unix网络编程>>,但是看这本书时有些内容你可能理解的不是很深刻,或者说只知其然而不知其所以然,那么如果你想搞懂的话那么我建议你可以看 ...

  9. IOS中 init和initialize

    一.init和initialize 1.方法类型 1> init属于对象方法,-开头 2> initialize属于类方法,+开头 2.调用时刻 1> init:每个对象初始化的时候 ...

  10. c#-Artificial Intelligence Class

    NET Artificial Intelligence Class http://www.codeproject.com/KB/recipes/aforge_neuro/neuro_src.zip