fcgiwrap 的简单使用

陪她去流浪 桃子 2016年06月15日 编辑 阅读次数:8687

FCGIWRAP: Simple FastCGI wrapper for CGI scripts。

首先说一下这个东西的作用。它为那些不支持直接运行 CGI脚本 的 Web 服务器提供一种运行 CGI脚本 的方式。

CGI 诞生已经非常久远了,由于它每次在处理一个请求(连接)时都要重新启动脚本(可执行文件),重新传递所有的环境变量(其中非常多是完全一样的),导致性能非常低下。虽然性能较低,但功不可没,后来出现了性能更高的 FastCGI

FastCGI 性能更高的原因在于,它是常驻内存的,一个 FastCGI 进程可以处理任意多个连接。后来又出现了 Spawn-FCGI,其使得 FastCGI 的进程数可以根据服务器的压力状况动态地创建 FastCGI 进程,这样,可伸缩性就更强了。

现在的 FastCGI 实现中,多数并没有实现标准的 FastCGI,导致性能依然不是特别高。同样没有完全避免重复的过程,比如:不变环境变量(服务器版本,用户家目录)的传递。但它不属于本文的范畴,我也就不多说了。

NGINX 就是一个只支持 FastCGI,不支持 CGI 的 HTTP(Web)服务器之一。也是我用得最多最熟悉的 Web 服务器。虽然 Apache 支持直接跑 CGI,但从来没用过它的我对它并不感冒,这里也就不再讨论了。

下面我将以 Ubuntu 为例简单介绍下。

fcgiwrap 的使用非常的简单。看源代码应该能看出来,不到 1000 行的程序,能有多复杂?

首先是安装(我就不编译了):

root@ubuntu:~# apt-get install fcgiwrap

,它把 spawn-fcgi 也装上了,不过也无关紧要,本文不会用到。

这玩意儿简单到不需要配置文件,只需要提供少数参数即可。

root@ubuntu:~# fcgiwrap -h
Usage: fcgiwrap [OPTION]
Invokes CGI scripts as FCGI.

fcgiwrap version 1.1.0

Options are:
  -f                    Send CGI's stderr over FastCGI
                        把 CGI 的 标准出错 也重定向到 FastCGI,多用于开发环境
  -c <number>           Number of processes to prefork
                        需要预先启动的子进程数
  -s <socket_url>       Socket to bind to (say -s help for help)
                        与 Web服务器 进行 FastCGI 通信用的 套接字(格式见下面)
  -h                    Show this help message and exit
  -p <path>             Restrict execution to this script. (repeated options will be merged)

Report bugs to Grzegorz Nosek <root@localdomain.pl>.
fcgiwrap home page: <http://nginx.localdomain.pl/wiki/FcgiWrap>

root@ubuntu:~# fcgiwrap -s help
Valid socket URLs are:
unix:/path/to/socket for Unix sockets
tcp:dot.ted.qu.ad:port for IPv4 sockets
tcp6:[ipv6_addr]:port for IPv6 sockets
root@ubuntu:~#

我直接使用的 unix域 形式:

root@ubuntu:~# # 后台跑起来
root@ubuntu:~# fcgiwrap -f -s unix:/var/run/fcgiwrap.socket &
[1] 1577
root@ubuntu:~# # 确实已经跑起来了
root@ubuntu:~# ps aux | grep '[f]cgiwrap'
root      1577  0.0  0.0   1600   512 pts/0    S    00:29   0:00 fcgiwrap -f -s unix:/var/run/fcgiwrap.socket
root@ubuntu:~# # 监听套接字存在
root@ubuntu:~# ls -l /var/run/fcgiwrap.socket
srwxr-xr-x 1 root root 0 Jun 15 00:29 /var/run/fcgiwrap.socket
root@ubuntu:~# # 因为我是用 root 执行的,所以得有这一步
root@ubuntu:~# chmod a+rw /var/run/fcgiwrap.socket
root@ubuntu:~# ls -l /var/run/fcgiwrap.socket
srwxrwxrwx 1 root root 0 Jun 15 00:29 /var/run/fcgiwrap.socket

OK,现在 Web服务器 和 FastCGI(Wrap) 已经跑起来了,接下来我写个简单的 CGI 脚本,用于打印出当前请求的资源和查询字符串。

#!/bin/bash

echo -ne 'Status: 200\r\n'
echo -ne 'Content-Type: text/plain\r\n'
echo -ne '\r\n'

echo 'PATH_INFO: ' $PATH_INFO
echo 'QUERY_STRING: ' $QUERY_STRING

exit 0

,这是很简单的一个 Shell 脚本,直接打印环境变量,我直接放在了家目录根下,文件名是 `echo`(/root/echo),注意修改为可执行。

下面是 nginx 的配置:

location / {
    fastcgi_param       SCRIPT_FILENAME     "/root/echo";
    fastcgi_param       PATH_INFO           $uri;
    fastcgi_param       QUERY_STRING        $args;
    fastcgi_param       HTTP_HOST           $server_name;
    fastcgi_pass        unix:/var/run/fcgiwrap.socket;
    include             fastcgi_params;     # 必须放在最后
}

,重启 nginx 后,用 curl 请求查看结果:

root@ubuntu:~# curl http://localhost/path/to/file?query=12345
PATH_INFO:  /path/to/file
QUERY_STRING:  query=12345
root@ubuntu:~#

可以看到的是,路径与查询信息都已经正确打印出来了,一切运行正常。

标签:nginx · FastCGI