标签 CGI 下的文章

通用网关接口(CGI)提供了使用任何语言生成动态网站的简易方法。

回到互联网的开端,当我第一次创建了我的第一个商业网站,生活是如此的美好。

我安装 Apache 并写了一些简单的 HTML 网页,网页上列出了一些关于我的业务的重要信息,比如产品概览以及如何联系我。这是一个静态网站,因为内容很少改变。由于网站的内容很少发生改变这一性质,因此维护起来也很简单。

静态内容

静态内容很简单,同时也很常见。让我们快速的浏览一些静态网页的例子。你不需要一个可运行网站来执行这些小实验,只需要把这些文件放到家目录,然后使用浏览器打开。你所看到的内容将和通过 Web 服务器提供这一文件看到的内容一样。

对于一个静态网站,你需要的第一件东西就是 index.html 文件,该文件通常放置在 /var/www/html 目录下。这个文件的内容可以非常简单,比如可以是像 “Hello, world” 这样一句短文本,没有任何 HTML 标记。它将简单的展示文本串内容。在你的家目录创建 index.html 文件,并添加 “hello, world” 作为内容(不需要引号)。在浏览器中通过下面的链接来打开这一文件:

file:///home/<你的家目录>/index.html

所以 HTML 不是必须的,但是,如果你有大量需要格式化的文本,那么,不用 HTML 编码的网页的结果将会令人难以理解。

所以,下一步就是通过使用一些 HTML 编码来提供格式化,从而使内容更加可读。下面这一命令创建了一个具有 HTML 静态网页所需要的绝对最小标记的页面。你也可以使用你最喜欢的编辑器来创建这一内容。

echo "<h1>Hello World</h1>" > test1.html

现在,再次查看 index.html 文件,将会看到和刚才有些不同。

当然,你可以在实际的内容行上添加大量的 HTML 标记,以形成更加完整和标准的网页。下面展示的是更加完整的版本,尽管在浏览器中会看到同样的内容,但这也为更加标准化的网站奠定了基础。继续在 index.html 中写入这些内容并通过浏览器查看。

<!DOCTYPE HTML PUBLIC "-//w3c//DD HTML 4.0//EN">
<html>
<head>
<title>My Web Page</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>

我使用这些技术搭建了一些静态网站,但我的生活正在改变。

动态网页

我找了一份新工作,这份工作的主要任务就是创建并维护用于一个动态网站的 CGI( 公共网关接口 Common Gateway InterfaceM )代码。字面意思来看,动态意味着在浏览器中生成的网页所需要的 HTML 是由每次访问页面时不同的数据所生成的。这些数据包括网页表单中的用户输入,以用来在数据库中进行数据查找,结果数据被一些恰当的 HTML 包围着并展示在所请求的浏览器中。但是这不需要非常复杂。

通过使用 CGI 脚本,你可以创建一些简单或复杂的交互式程序,通过运行这些程序能够生成基于输入、计算、服务器的当前条件等改变的动态页面。有许多种语言可以用来写 CGI 脚本,在这篇文章中,我将谈到的是 Perl 和 Bash ,其他非常受欢迎的 CGI 语言包括 PHP 和 Python 。

这篇文章不会介绍 Apache 或其他任何 web 服务器的安装和配置。如果你能够访问一个你可以进行实验的 Web 服务器,那么你可以直接查看它们在浏览器中出现的结果。否则,你可以在命令行中运行程序来查看它们所创建的 HTML 文本。你也可以重定向 HTML 输出到一个文件中,然后通过浏览器查看结果文件。

使用 Perl

Perl 是一门非常受欢迎的 CGI 脚本语言,它的优势是强大的文本操作能力。

为了使 CGI 脚本可执行,你需要在你的网站的 httpd.conf 中添加下面这行内容。这会告诉服务器可执行 CGI 文件的位置。在这次实验中,不必担心这个问题。

ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

把下面的 Perl 代码添加到文件 index.cgi,在这次实验中,这个文件应该放在你的家目录下。如果你使用 Web 服务器,那么应把文件的所有者更改为 apache.apache,同时将文件权限设置为 755,因为无论位于哪,它必须是可执行的。

#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "<html><body>\n";
print "<h1>Hello World</h1>\n";
print "Using Perl<p>\n";
print "</body></html>\n";

在命令行中运行这个程序并查看结果,它将会展示出它所生成的 HTML 内容

现在,在浏览器中查看 index.cgi 文件,你所看到的只是文件的内容。浏览器需要将它看做 CGI 内容,但是,Apache 不知道需要将这个文件作为 CGI 程序运行,除非 Apache 的配置中包括上面所展示的 ScriptAlias 定义。没有这一配置,Apache 只会简单地将文件中的数据发送给浏览器。如果你能够访问 Web 服务器,那么你可以将可执行文件放到 /var/www/cgi-bin 目录下。

如果想知道这个脚本的运行结果在浏览器中长什么样,那么,重新运行程序并把输出重定向到一个新文件,名字可以是任何你想要的。然后使用浏览器来查看这一文件,它包含了脚本所生成的内容。

上面这个 CGI 程序依旧生成静态内容,因为它总是生成相同的输出。把下面这行内容添加到 CGI 程序中 “Hello, world” 这一行后面。Perl 的 system 命令将会执行跟在它后面的 shell 命令,并把结果返回给程序。此时,我们将会通过 free 命令获得当前的内存使用量。

system "free | grep Mem\n";

现在,重新运行这个程序,并把结果重定向到一个文件,在浏览器中重新加载这个文件。你将会看到额外的一行,它展示了系统的内存统计数据。多次运行程序并刷新浏览器,你将会发现,内存使用量应该是不断变化的。

使用 Bash

Bash 可能是用于 CGI 脚本中最简单的语言。用 Bash 来进行 CGI 编程的最大优势是它能够直接访问所有的标准 GNU 工具和系统程序。

把已经存在的 index.cgi 文件重命名为 Perl.index.cgi,然后创建一个新的 `index.cgi 文件并添加下面这些内容。记得设置权限使它可执行。

#!/bin/bash
echo "Content-type: text/html"
echo ""
echo '<html>'
echo '<head>'
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
echo '<title>Hello World</title>'
echo '</head>'
echo '<body>'
echo '<h1>Hello World</h1><p>'
echo 'Using Bash<p>'
free | grep Mem
echo '</body>'
echo '</html>'
exit 0

在命令行中执行这个文件并查看输出,然后再次运行并把结果重定向到一个临时结果文件中。然后,刷新浏览器查看它所展示的网页是什么样子。

结论

创建能够生成许多种动态网页的 CGI 程序实际上非常简单。尽管这是一个很简单的例子,但是现在你应该看到一些可能性了。


via: https://opensource.com/article/17/12/cgi-scripts

作者:David Both 译者:ucasFL 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在新闻组和邮件列表里、在计算机科学实验室里、在各大陆之间,流传着一个神秘的故事,那是关于 Perl 与动态网站之间的不得不说的往事。

早期互联网历史中,有一些脍炙人口的开创性事件:如 蒂姆·伯纳斯·李 Tim Berners-Lee 在邮件组上宣布 WWW-project 的那天,该文档随同 CERN 发布的项目代码进入到了公共域,以及 1993 年 1 月的第一版 NCSA Mosaic 浏览器。虽然这些独立的事件是相当重要的,但是当时的技术的开发已经更为丰富,不再是由一组的孤立事件组成,而更像是一系列有内在联系的故事。

这其中的一个故事描述的是网站是如何变成动态的,通俗说来就是我们如何使服务器除了提供静态 HTML 文档之外做更多的事。这是个流传在新闻组和邮件列表间、计算机科学实验室里、各个大陆之间的故事,重点不是一个人,而是一种编程语言:Perl。

CGI 脚本和信息软件

在上世纪 90 年代中后期,Perl 几乎和动态网站是同义词。Perl 是一种相对来说容易学习的解释型语言,并且有强大的文本处理特性,使得它能够很容易的编写脚本来把一个网站关联到数据库、处理由用户发送的表单数据,当然,还要创造那些上世纪 90 年代的网站的经典形象——计数器和留言簿。

类似的网站特性渐渐的变成了 CGI 脚本的形式,其全称为 通用网关接口 Common Gateway Interface 首个实现由 Rob McCool 于 1993 年 11 月在 NCSA HTTPD 上完成。CGI 是目的是直面功能,并且在短短几年间,任何人都可以很容易的找到一些由 Perl 写的预制的脚本存档。有一个声名狼籍的案例就是 Matt's Scripts Archive,这是一种流行却包含各种安全缺陷的源代码库,它甚至使得 Perl 社区成员创建了一种被称为 Not Matt‘s Scripts 的更为专业的替换选择。

在当时,无论是业余爱好者,还是职业程序员都采用 Perl 来制作动态网站和应用,Tim O’Reilly 创造了词汇 “信息软件” infoware 来描述网站和 Perl 怎样成为变化中的计算机工业的一部分。考虑到 Yahoo!和 Amazon 带来的创新,O‘Reilly 写道:“传统软件在大量的软件中仅仅包含了少量的信息;而信息软件则在少量的软件中包含了大量的信息。” Perl 是一种像瑞士军刀一样的完美的小而强大的工具,它支撑了信息媒体从巨大的网站目录向早期的用户生成内容(UGC)平台的转变。

题外话

尽管使用 Perl 来制作 CGI 简直是上佳之选,但是编程语言和不断提升中的动态网站之间的关系变得更加的密切与深入。从第一个网站(在 1990 年的圣诞节前)出现到 1993 年 McCool 实现 CGI 的短暂时期内,Web 上的各种东西,比如表单、图片以及表格,就这么逐渐出现在上世纪 90 年代乃至后来。尽管伯纳斯·李也对这些早期的岁月产生了影响,但是不同的人看到的是 Web 不同的潜在作用,并将它推向各自不同的方向。一方面,这样的结果来自一些著名的辩论,例如 HTML 应该和 SGML 保持多近的关系是否应该实现一个图像标签等等。在另一方面,在没有直接因素影响的情况下改变是极其缓慢的。后者已经很好的描述了动态网站是如何发展的。

从某种意义上说,第一个“网关”的诞生可以追溯到 1991 至 1992 年之间(LCTT 译注:此处所谓“网关”的意义请参照 CGI 的定义),当时伯纳斯·李和一些计算机科学家与超文本爱好者编写服务程序使得一些特定的资源能够连接到一起,例如 CERN 的内部应用程序、通用的应用程序如 Oracle 数据库、广域信息查询系统(WAIS) 等等。(WAIS 是 Web 的前身,上世纪 80 年代后期开发,其中,开发者之一 Brewster Kahle,是一个数字化图书管理员和 Internet Archive 的创始人。)可以这样理解,“网关”就是一个被设计用来连接其它 Web、数据库或者应用程序的定制的 Web 服务器。任何的动态功能就意味着在不同的端口上运行另外一个守护进程(参考阅读,例如伯纳斯·李对于在网站上如何添加一个搜索功能 的描述)。伯纳斯·李期望 Web 可以成为不同信息系统之间的通用接口,并且鼓励建立单一用途服务。他也提到 Perl 是一种强大的(甚至是不可思议)、可以将各种东西组合起来的语言。

然而,另一种对“网关”的理解指出它不一定是一个定制设备,可能只是一个脚本,一个并不需要额外服务器的低吞吐量的附加脚本。这种形式的首次出现是有争议性的 Jim Davis 的 Gateway to the U Mich Geography server,于 1992 年的 11 月发布在了 WWW-talk 邮件列表中。Davis 的脚本是使用 Perl 编写的,是一种 Web API 的原型,基于格式化的用户查询从另外的服务器拉取数据。我们来说明一下这两种对于网关的理解的不同之处,伯纳斯·李回复了 Davis 的邮件,期望他和 Michigan 服务器的作者“能够达成某种共识”,“从网络的角度来看的话”仅使用一台服务器来提供这样的信息可能会更有意义。伯纳斯·李,可能是期待着 Web 的发明者可以提出一种有秩序的信息资源访问方式。这样从不同服务器上拉取数据的网关和脚本意味着一种潜在的 Web 的质的变化,虽然不断增多,但也可能有点偏离了伯纳斯·李的原始观点。

回到 Perl HTTPD

在 Davis 的地理服务器上的网关向标准化的、低吞吐量的、通过 CGI 方式实现的脚本化网关迈进的一步中,Perl HTTPD 的出现是很重要的事件,它是 1993 年初由印地安纳大学的研究生 Marc Van Heyningen 在 布卢明顿 Bloomington 完全使用 Perl 语言实现的一个 Web 服务器程序。从 Van Heyningen 给出的设计原则来看,基于使用 Perl 就不需要任何的编译过程这样一种事实,使得它能够成为一种极易扩展的服务器程序,这个服务器包含了“一个向代码中增加新特性时只要简单的重启一下就可以,而不会有任何的宕机时间的特性”,使得这个服务器程序可以频繁的加入新功能。

Perl HTTPD 代表了那种服务器程序应该是单一、特定目的的观点。相应的,这种模式似乎暗示了在 Web 开发中像这样渐进式的、持续测试的软件产品可能会最终变成一种共识。Van Heyningen 在后来提到过他从头编写这样一个服务器程序的初衷是当时没有一种简便的方式使用 CERN 服务器程序来生成“虚拟文档”(例如,动态生成的页面),他打趣说使用 Perl 这样的“神之语言”来写可能是最简单的方式了。在他初期编写的众多脚本中有一个 Sun 操作系统的用户手册的 Web 界面,以及 Finger 网关(这是一种早期用来共享计算机系统信息或者是用户信息的协议)。

虽然 Van Heyningen 将印地安纳大学的服务器主要用来连接现存的信息资源,他和研究生们同时也看见了作为个人发布形式的潜在可能。其中一件广为人知事件是在 1993-1994 年之间围绕着一个著名的加拿大案件而公布的一系列的文件、照片和新闻故事,与此形成鲜明对比的是,所有的全国性媒体都保持了沉默。

Perl HTTPD 没有坚持到现在的需要。今天,Van Heyningen 回忆起这个程序的时候认为这个程序只是当时的一个原型产品。它的原始目的只是向那些已经选择了 Gopher 作为大学的网络界面的资深教员们展示了网络的另一种利用方式。Van Heyningen 以一种基于 Web 的、可搜索的出版物索引的方式,用代码回应了他的导师们的虚荣。就是说,在服务器程序技术方面关键创新是为了赢得争论的胜利而诞生的,在这个角度上来看代码做到了所有要求它所做的事。

不管该服务器程序的生命是否短暂,伴随者 Perl HTTPD 一起出现的理念已经传播到了各个角落。Van Heyningen 开始收到了获取该代码的请求,而后将它分享到了网上,并提示说,需要了解一些 Perl 就可以将它移植到其它操作系统(或者找到一个这样的人也行)。不久之后,居住在 奥斯汀 Austin 的程序员 Tony Sanders 开发了一个被称为 Plexus 的轻便版本。Sander 的服务器程序是一款全功能的产品,并且同样包含了 Perl HTTPD 所建议的易扩展性,而且添加一些新的特性如图片解码等。Plexus 直接影响了 Rob McCool 给 NCSA HTTPD 服务器上的脚本开发的“htbin”,并且同样影响到了不久之后诞生的通用网关接口(CGI)。

在这些历史遗产之外,感谢妙不可言的 互联网时光机 Internet Archive 使得 Perl HTTPD 在今天依然保留在一种我们依然可以获取的形式,你可以从这里下载 tarball

历史展望

对于技术世界的颠覆来说,技术的改变总是在一个相互对立的过程中。现有的技术是思考新技术的基础与起点。过时的编程形式启迪了今天人们做事的新方式。网络世界的创新可能看起来更像是对于旧技术的扩展,不仅仅是 Perl。

在萌芽事件的简单的时间轴之外,Web 历史学者也许可以从 Perl 获取更多的线索。其中一部份的挑战在于材料的获取。更多需要做的事情包括从可获取的大量杂乱的数据中梳理出它的结构,将分散在邮件列表、归档网站,书本和杂志中的信息内容组合在一起。还有一部分的挑战是需要认识到 Web 的历史不仅仅是新技术发布的日子,它同时包括了个人记忆、人类情感与社会进程等,并且这不仅仅是单一的历史线而是有许许多多条相似的历史线组合而成的。就如 Perl 的信条一样“ 殊途同归。 There's More Than One Way To Do It.

(题图来自:pinterest.com


via: https://opensource.com/life/16/11/perl-and-birth-dynamic-web

作者:Michael Stevenson 译者:wcnnbdk1 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

你是否想使用Python语言创建一个网页,或者处理用户从web表单输入的数据?这些任务可以通过Python CGI(公用网关接口)脚本以及一个Apache web服务器实现。当用户请求一个指定URL或者和网页交互(比如点击""提交"按钮)的时候,CGI脚本就会被web服务器启用。CGI脚本调用执行完毕后,它的输出结果就会被web服务器用来创建显示给用户的网页。

配置Apache web服务器,让其能运行CGI脚本

在这个教程里,我们假设Apache web服务器已经安装好,并已运行。这篇教程使用的Apache web服务器(版本2.2.15,用于CentOS发行版6.5)运行在本地主机(127.0.0.1),并且监听80端口,如下面的Apache指令指定一样:

ServerName 127.0.0.1:80
Listen 80

下面举例中的HTML文件存放在web服务器上的/var/www/html目录下,并通过DocumentRoot指令指定(指定网页文件所在目录):

DocumentRoot "/var/www/html"

现在尝试请求URL:http://localhost/page1.html

这将返回web服务器中下面文件的内容:

/var/www/html/page1.html

为了启用CGI脚本,我们必须指定CGI脚本在web服务器上的位置,需要用到ScriptAlias指令:

ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

以上指令表明CGI脚本保存在web服务器的/var/www/cgi-bin目录,请求URL里包含/cgi-bin/的将会搜索这个目录下的CGI脚本。

我们必须还要明确CGI脚本在/var/www/cgi-bin目录下有执行权限,还要指定CGI脚本的文件扩展名。使用下面的指令:

<Directory "/var/www/cgi-bin">
    Options +ExecCGI
    AddHandler cgi-script .py
</Directory>

下面访问URL:http://localhost/cgi-bin/myscript-1.py

这将会调用web服务器中下面所示脚本:

/var/www/cgi-bin/myscript-1.py

创建一个CGI脚本

在创建一个Python CGI脚本之前,你需要确认你已经安装了Python(这通常是默认安装的,但是安装版本可能会有所不同)。本篇教程使用的脚本是使用Python版本2.6.6编写的。你可以通过下面任意一命令(-V和--version参数将显示所安装Python的版本号)检查Python的版本。

$ python -V
$ python --version

如果你的Python CGI脚本要用来处理用户输入的数据(从一个web输入表单),那么你将需要导入Python cgi模块。这个模块可以处理用户通过web输入表单输入的数据。你可以在你的脚本中通过下面的语句导入该脚本:

import cgi

你也必须修改Python CGI脚本的执行权限,以防止web服务器不能调用。可以通过下面的命令增加执行权限:

# chmod o+x myscript-1.py

Python CGI例子

涉及到Python CGI脚本的两个方案将会在下面讲述:

  • 使用Python脚本创建一个网页
  • 读取并显示用户输入的数据,并且在网页上显示结果

注意:Python cgi模块在方案2中是必需的,因为这涉及到用户从web表单输入数据。

例子1 :使用Python脚本创建一个网页

对于这个方案,我们将通过创建包含一个单一提交按钮的网页/var/www/html/page1.html开始。

<html>
<h1>Test Page 1</h1>
<form name="input" action="/cgi-bin/myscript-1.py" method="get">
<input type="submit" value="Submit">
</form>
</html>

当"提交"按钮被点击,/var/www/cgi-bin/myscript-1.py脚本将被调用(通过action参数指定)。通过设置方法参数为"get"来指定一个"GET"请求,服务器将会返回指定的网页。/var/www/html/page1.html在浏览器中的显示情况如下:

/var/www/cgi-bin/myscript-1.py的内容如下:

#!/usr/bin/python
print "Content-Type: text/html"
print ""
print "<html>"
print "<h2>CGI Script Output</h2>"
print "<p>This page was generated by a Python CGI script.</p>"
print "</html>" 

第一行声明表示这是使用 /usr/bin/python命令运行的Python脚本。"Content-Type: text/html"打印语句是必需的,这是为了让web服务器知道接受自CGI脚本的输出类型。其余的语句用来输出HTML格式的其余网页内容。

当"Submit"按钮点击,下面的网页将返回:

这个例子的要点是你可以决定哪些信息可以被CGI脚本返回。这可能包括日志文件的内容,当前登陆用户的列表,或者今天的日期。在你处理时拥有所有python库的可能性是无穷无尽的。

例子2:读取并显示用户输入的数据,并将结果显示在网页上

对于这个方案,我们将通过创建一个含有三个输入域和一个提交按钮的网页/var/www/html/page2.html开始。

<html>
<h1>Test Page 2</h1>
<form name="input" action="/cgi-bin/myscript-2.py" method="get">
First Name: <input type="text" name="firstName"><br>
Last Name: <input type="text" name="lastName"><br>
Position: <input type="text" name="position"><br>
<input type="submit" value="Submit"> 
</form>
</html>

当"Submit"按钮点击,/var/www/cgi-bin/myscript-2.py脚本将被执行(通过action参数指定)。/var/www//html/page2.html显示在web浏览器中的图片如下所示(注意,三个输入域已经被填写好了):

/var/www/cgi-bin/myscript-2.py的内容如下:

#!/usr/bin/python
import cgi
form = cgi.FieldStorage()
print "Content-Type: text/html"
print ""
print "<html>"
print "<h2>CGI Script Output</h2>"
print "<p>"
print "The user entered data are:<br>"
print "<b>First Name:</b> " + form["firstName"].value + "<br>"
print "<b>Last Name:</b> " + form["lastName"].value + "<br>"
print "<b>Position:</b> " + form["position"].value + "<br>"
print "</p>"
print "</html>"

正如前面提到,import cgi语句用来确保能够处理用户通过web输入表单输入的数据。web输入表单被封装在一个表单对象中,叫做cgi.FieldStorage对象。一旦开始输出,"Content-Type: text/html"是必需的,因为web服务器需要知道接受自CGI脚本的输出格式。用户输入的数据在包含form["firstName"].value,form["lastName"].value,和 form["position"].value的语句中可以得到。那些中括号中的名称和/var/www/html/page2.html文本输入域中定义的名称参数一致。

当网页上的"Submit"按钮被点击,下面的网页将被返回。

这个例子的要点就是你可以很容易地读取并显示用户在web表单上输入的数据。除了以字符串的方式处理数据,你也可以用Python将用户输入的数据转化为可用于数值计算的数字。

结论

本教程演示了如何使用Python CGI脚本创建网页并处理用户在网页表单输入的数据。查阅更多关于Apache CGI脚本的信息,点击这里。查阅更多关于Python cgi模块的信息,点击这里


via: http://xmodulo.com/create-use-python-cgi-scripts.html

作者:Joshua Reed 译者:su-kaiyao 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出