使用 SHELL 实现CGI

通用网关接口 Common Gateway Interface

# CGI是Web服务器和外部程序之间的一个接口
# 利用CGI程序可以处理从客户端发送出来的表单和数据并对此做出相关操作。这种反应可以是HTML、图片、声音、视频等可以在浏览器窗体上出现的任何数据
# 通用网关接口有两个含义:
# 1.首先它为客户端用户通过www获取Internet上的其他服务,例如Archie、WAIS、Database等提供了一个接口
# 虽然不能直接在www上访问这些服务,但是可以通过CGI程序和Web服务器访问它们
# 2.其次它就是编写的程序和Web服务器间的接口标准,所编写的处理客户端有关信息的程序必须遵循这个标准

# CGI如何在客户端的Web浏览器和Web服务器间工作
# 当客户端向Web服务器请求HTML文件时,服务器收到请求后去寻找该文件并返回给客户端
# 当客户端请求的是一个CGI程序时,Web服务器将激活客户端所请求的CGI程序
# 此时Web服务器所起的作用就好像是客户端和CGI程序间的中间人

# --------------------------------------------------

CGI程序的工作一般可以分为以下几个步骤

1.客户端发出请求
# 首先客户端浏览器发出一个请求给Web服务器。如果这个请求是一个普通的文件,如HTML、GIF、JPEG文件,Web服务器就将文件直接传送给客户端的浏览器
# 如果请求是一个CGI程序或外部应用,Web服务器将激活相应的CGI程序
# 例如客户端传送来的请求可能是对一个数据库的检索,此时一个相应的CGI程序将被Web服务器激活
# 这个CGI程序将根据客户端要求的准则去检索相应的数据库,并通过Web服务器将结果传送给客户端

2.Web服务器激活CGI程序
# 当Web服务器发现客户端浏览器传送来的请求不是普通文件而是一个CGI程序时
# Web服务器就要激活这个CGI程序并执行它,比如:http://www.example.com/wiki.cgi
# 在这个CGI程序被执行前,Web服务器要为该CGI程序设置一些环境变量,这些环境变量被服务器用来向CGI程序传递一些非常重要的信息
# 例如当前Web服务器的状态、谁发出的调用等等。Web服务器为CGI程序所设置的环境变量的使用和正常的环境变量的使用没有任何区别
# 当CGI程序运行结束时,Web服务器为它设置的环境变量也随着消失,每个被激活的CGI程序都有自己唯一的一组环境变量

3.CGI程序对客户端的请求做出反应
# CGI程序通过环境变量或其他途经读取Web服务器所提供的客户端的输入数据并对这些数据进行处理
# 如果有必要CGI程序还要和一些外部的服务例如Archie、WAIS和Database等发生联系
# 最后CGI程序将通过Web服务器将处理结果传送给客户端,CGI程序可以根据需要产生各种类型的数据

4.Web服务器将CGI程序的处理结果传送给客户端
# Web服务器收到CGI程序的处理结果后将对CGI程序的输出进行检查
# 如有必要,将为CCI程序的输出结果加上一些HTTP协议所必须的HTTP头信息
# 检查完成后将把CGI程序的输出传送给客户端
 
5. Web服务器中断和客户端浏览器的连接

6. Web浏览器将CGI程序的输出显示在浏览器窗体上

-------------------------------------------------- SHELL CGI Example
#!/bin/bash

echo 'Status: 200 OK'
echo 'Content-Type: text/html; charset=utf-8'
echo 'Cache-Control: no-cache'
echo 'Pragma: no-cache'
echo
echo '<html>'
echo '<head>'
echo '<title>It works!</title>'
echo '</head>'
echo '<body>'
echo '<h1>It works!</h1>'
echo '<hr />'
echo "<h2>Your IP address is: <tt>$REMOTE_ADDR</tt></h2>"
echo '<ul style="font-size: medium">'
if [[ "$REMOTE_ADDR" =~ ':' ]]
then
    echo '<li style="color: darkgreen">You are using IPv6.</li>'
else
    echo '<li style="color: red">You are using IPv4.</li>'
fi
if [ "$SERVER_PORT" == 443 ]
then
    echo '<li style="color: darkgreen">You are using HTTPS.</li>'
else
    echo '<li style="color: red">You are not using HTTPS.</li>'
fi
echo '</ul>'
echo '<h2>Your User-Agent is:</h2>'
echo "<blockquote><pre style=\"font-size: large\">$HTTP_USER_AGENT</pre></blockquote>"
echo '</body>'
echo '</html>'
echo

# -------------------------------------------------- Python使用CGIHTTPServer调用shell作为cgi脚本

mkdir -p /data/cgi-bin
cat >> /data/cgi-bin <'EOF'
#!/bin/bash
# 脚本注释下方的前三行是必须的
# 第一行用于指定脚本执行使用的解释器
# 第二行和第三行是HTTP协议规范,在发送HTML正文之前要发送MIME头和空行
echo "Content-Type:text/html"
echo "" 
echo "hello world!"
EOF

# 执行
python -m CGIHTTPServer

# 然后在浏览器中输入: http://<ip>:8000/cgi-bin/hello.sh
# 即可调用cgi脚本

# -------------------------------------------

# nginx下启用cgi脚本(py,shell)

# 安装 fcgiwrap,spawn-fcgi,fcgi
yum -y install autoconf automake libtool fcgi fcgi-devel spawn-fcgi

# 安装fcgiwrap
wget https://github.com/gnosek/fcgiwrap/archive/master.zip -O fcgiwrap.zip
unzip fcgiwrap.zip
cd fcgiwrap-master
autoreconf -i
./configure
make
make install

# 编辑spawn-fcgi配置文件
vi /etc/sysconfig/spawn-fcgi
FCGI_SOCKET=/var/run/fcgiwrap.socket
FCGI_PROGRAM=/usr/local/sbin/fcgiwrap
FCGI_USER=nginx
FCGI_GROUP=nginx
FCGI_EXTRA_OPTIONS="-M 0700"OPTIONS="-u $FCGI_USER -g $FCGI_GROUP -s $FCGI_SOCKET -S $FCGI_EXTRA_OPTIONS -F 1 -P /var/run/spawn-fcgi.pid -- $FCGI_PROGRAM"

# 添加开机启动
chkconfig spawn-fcgi on

# 启动spawn-fcgi服务
service spawn-fcgi start

# Nginx
server {        
        root /data;

        location ~* .(py|sh)$ {
            gzip off;            
            fastcgi_pass unix:/var/run/fcgiwrap.socket;            
            include fastcgi_params;            
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }

        location ~* .(jpg|gif|png|js|css)$ {
            if (-f $request_filename) {
                expires max;
                break;         
            }        
        }
}
网关协议 CGI、FastCGI、WSGI 的区别

# CGI方式在遇到连接请求(用户请求)要先创建/激活一个CGI进程然后处理请求,处理后结束该子进程
# 即fork-and-execute模式。所以用CGI方式的服务器有多少连接请求就会有多少cgi子进程
# 子进程反复加载是cgi性能低下的主要原因

FastCGI
# FastCGI是可伸缩、高速地在HTTPserver和动态脚本语言间通信的接口
# 多数流行的HTTPserver都支持FastCGI,包括Apache、Nginx、lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP
# FastCGI从CGI发展而来。传统CGI方式主要缺点是性能差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析
# FastCGI像是个常驻型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次
# 它还支持分布式的运算, 即FastCGI程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求
# FastCGI是语言无关、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高性能
# FastCGI接口方式采用C/S结构,可将HTTP服务器和脚本解析服务器分开

FastCGI 工作流程
# WebServer启动时载入FastCGI进程管理器(PHP-CGI或PHP-FPM或者spawn-cgi)
# FastCGI进程管理器自身初始化,启动多个CGI解释器进程 (可见多个php-cgi) 并等待来自Web Server的连接
# 当客户端请求到达WebServer时,FastCGI进程管理器选择并连接到一个CGI解释器。Webserver将CGI环境变量和标准输入发送到FastCGI子进程php-cgi
# FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回WebServer
# 当FastCGI子进程关闭连接时请求便告处理完成
# FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在WebServer中)的下一个连接。在CGI模式中php-cgi在此便退出

PHP-CGI
# PHP-CGI是PHP自带的FastCGI管理器
# PHP-CGI的不足:
# php-cgi变更ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启
# 直接杀死php-cgi进程php就不能运行了 (PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程)

Spawn-FCGI
# Spawn-FCGI是通用的FastCGI管理服务器,它是lighttpd中的一部份
# Spawn-FCGI是个很早期的程序,瞻仰一下即可

PHP-FPM
# PHP-FPM是PHP的FastCGI管理器,是只用于PHP的
# PHP-FPM其实是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中
# 它的功能包括:
#   支持平滑停止/启动的高级进程管理功能
#   可以工作于不同的 uid/gid/chroot 环境下,并监听不同的端口和使用不同的ini配置文件(可取代safe_mode的设置)
#   stdout和stderr日志记录
#   在发生意外情况的时候能够重启并缓存被破坏的opcode
#   文件上传优化支持
#   慢日志–记录脚本(不仅记录文件名,还记录PHP backtrace信息,可使用ptrace或类似工具读取和分析远程进程的运行数据)运行所导致的异常缓慢
#   fastcgi_finish_request() – 特殊功能:用于在请求完成和刷新数据后,继续在后台执行耗时的工作(录入视频转换、统计处理等)
#   动态/静态子进程产生;
#   基本SAPI运行状态信息(类似Apache的 mod_status)
#   基于ini的配置文件

WSGI
# Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)
# 是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口
# 自从WSGI被开发出来以后,许多其它语言中也出现了类似接口
# WSGI是作为Web服务器与Web应用程序或应用框架之间的一种低级别的接口,以提升可移植Web应用开发的共同点。WSGI是基于现存的CGI标准而设计的
# WSGI区分为两个部份:一为服务器或网关,另一为应用程序或应用框架
# 在处理WSGI请求时服务器会为应用程序提供环境资讯及一个回呼函数(Callback Function)
# 当应用程序完成处理请求后,透过前述的回呼函数,将结果回传给服务器
# 所谓的WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用
# 从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。"中间件"组件可以执行以下功能:
#   1.重写环境变量后根据目标URL将请求消息路由到不同的应用对象
#   2.允许在一个进程中同时运行多个应用程序或应用框架
#   3.负载均衡和远程处理,通过在网络上转发请求和响应消息
#   4.进行内容后处理,例如应用XSLT样式表

WSGI Server/gateway
# wsgi server可理解为一个符合wsgi规范的web server
# 接收request请求,封装一系列环境变量,按照wsgi规范调用注册的wsgi app,最后将response返回给客户端
#   1.服务器创建socket,监听端口,等待客户端连接
#   2.当有请求来时服务器解析客户端信息放到环境变量environ中并调用绑定的handler来处理请求
#   3.handler解析这个http请求,将请求信息例如method,path等放到environ中
#   4.wsgi handler再将一些服务器端信息也放到environ中,最后服务器信息,客户端信息,本次请求信息全部都保存到了环境变量environ中
#   5.wsgi handler调用注册的wsgi app并将environ和回调函数传给wsgi app
#   6.wsgi app 将reponse header/status/body 回传给wsgi handler
#   7.最终handler还是通过socket将response信息塞回给客户端

WSGI MiddleWare
# 有些功能可能介于服务器程序和应用程序之间,例如服务器拿到了客户端请求的URL, 不同的URL需要交由不同的函数处理
# 这个功能叫做 URL Routing,这个功能就可以放在二者中间实现,这个中间层就是 middleware
# middleware对服务器程序和应用是透明的,也就是说,服务器程序以为它就是应用程序,而应用程序以为它就是服务器
# 即middleware需把自己伪装成服务器,接受应用程序,调用它,同时middleware还要把自己伪装成应用程序,传给服务器程序

uWSGI
# uWSGI项目旨在为部署分布式集群的网络应用开发一套完整的解决方案

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值