php on nginx - downgoon/hello-world GitHub Wiki

内容提要

讲义目标

  • 安装运行 PHP HelloWorld
  • 基于Nginx运行PHP
  • Nginx cgi 和 fast-cgi

总结回顾

这节仅供总结用。

  • php一种解析语言,需要php解析器支持。比如 php hello.php 就是用php解析器运行hello.php程序。
  • php提供web服务:php一般借助nginx提供HTTP服务,nginx把请求转发到 php-fpm 上(默认侦听在9000端口)。跟Java不同的是,PHP没有单独的Http Server,php-fpm 不是web容器,而是 fast-cgi的server。
  • cgi/fast-cgi: web最早就是网页服务,都是静态网页,那时候还没有动态网页。慢慢的动态网页来了,HTTP服务器必须考虑有一部分请求必须交由程序员开发,于是HTTP设计者得留出一个“接口”:HTTP请求到HTTP服务器后,服务器把这个请求给另外一个程序,这个程序接收输入,处理,然后返回输出。这个定义“输入”、“输出”规格和处理时上下文环境的标准就叫cgi (common gateway interface)。这个东西跟J2EE体系的servlet思考的问题是一样的,都是在HTTP服务器上,留出一个给程序员拓展开发的“接口”,只是实现技术不一样。

第一节:PHP Hello World

安装PHP

安装PHP非常简单:

wget http://cn2.php.net/distributions/php-7.1.2.tar.gz
tar zxvf php-7.1.2.tar.gz && cd php-7.1.2
./configure && make && make install

说明

http://cn2.php.net/distributions/php-7.1.2.tar.gz是官方推荐的中国区镜像。官方下载: http://www.php.net/downloads.php

安装完毕后,出现如下:

ll /usr/local/bin/ | grep php
-rwxr-xr-x 1 root root 30699271 Mar  9 15:40 php
-rwxr-xr-x 1 root root 30521123 Mar  9 15:40 php-cgi
-rwxr-xr-x 1 root root     2197 Mar  9 15:40 php-config
-rwxr-xr-x 1 root root 31615175 Mar  9 15:40 phpdbg
-rwxr-xr-x 1 root root     4547 Mar  9 15:40 phpize

其中:/usr/bin/php 是 PHP 的解析器,它能解析并执行PHP。

执行PHP

  • 编写PHP

编写 hello.php 文件:

<?php echo "Hello World PHP\r\n" ?>
  • 运行PHP
$ php hello.php
Hello World PHP

常见错误

安装过程可能会遇到如下错误:

configure: error: xml2-config not found. Please check your libxml2 installation.

该错误是缺少依赖,直接安装就好:

yum install libxml2
yum install libxml2-devel -y

which xml2-config 命令检查是否安装好,如果输出: /usr/bin/xml2-config 表示安装好了。

或者 rpm -qa | grep libxml2 检查下。


第2节:PHP on Nginx

上一节讲了用php解析器直接运行hello.php程序。这节讲如何让PHP提供web服务。实际上PHP不能直接提供HTTP服务,而需要借助Nginx提供HTTP服务,然后Nginx转发给PHP的 php-fpm 服务,再由php-fpm来加载解析*.php文件。

原理概述

这里nginx与php-fpm之间的通信,不是走HTTP协议,而是 FastCGI标准。简单说,什么是FastCGI呢? 先要说CGI,FastCGI只是速度更快的CGI。CGI解决的问题是什么?

web最早就是网页服务,都是静态网页,那时候还没有动态网页。慢慢的动态网页来了,HTTP服务器必须考虑有一部分请求必须交由程序员开发,于是HTTP设计者得留出一个“接口”:HTTP请求到HTTP服务器后,服务器把这个请求给另外一个程序,这个程序接收输入,处理,然后返回输出。这个定义“输入”、“输出”规格和处理时上下文环境的标准就叫cgi (common gateway interface)。这个东西跟J2EE体系的servlet思考的问题是一样的,都是在HTTP服务器上,留出一个给程序员拓展开发的“接口”,只是实现技术不一样。补充下,CGI定义的是交互标准,跟语言无关,我们可以用C/C++写cgi程序,也可以用php,用python等。

了解CGI后,php on nginx的结构是:

http request on php.png

实战练习

安装 php-fpm 模块

默认php编译安装是不包含php-fpm的,需要:

./configure --enable-fpm  && make && make install

安装后,看到如下,表示安装好:

$ which php-fpm
/usr/local/sbin/php-fpm

运行 php-fpm

安装好后,便要运行php-fpm,它是一个FastCGI Server,默认侦听9000端口。

运行它很简单,直接php-fpm即可。(如同运行 nginx 一样) 它默认加载的配置文件是:/usr/local/etc/php-fpm.conf

注意

php-fpm 默认只提供了配置模板,需要我们改下文件名:

cp /usr/local/etc/php-fpm.conf.default /usr/local/etc/php-fpm.conf
cp /usr/local/etc/php-fpm.d/www.conf.default /usr/local/etc/php-fpm.d/www.conf

并修改 vi /usr/local/etc/php-fpm.conf 的最后一行为:

include=/usr/local/etc/php-fpm.d/*.conf

这样做的目的是:以便主配置php-fpm.conf,能够加载子目录下的子配置 php-fpm.d/*.conf

php-fpm 运行风格上,几乎跟nginx一模一样。

  1. 直接运行:都是直接运行,加载默认配置,都是后台运行。
  2. 配置文件:配置文件都是分“主从”,一个主配置文件,在主配置文件中include 子目录/*.conf 形式。
  3. 侦听端口:侦听端口都在子配置里面。php-fpm的是 /usr/local/etc/php-fpm.d/www.conflisten = 127.0.0.1:9000配置项。

最后,运行php-fpm,然后查看:

$ ps aux | grep php-fpm
root      2572  0.0  0.0 103248   824 pts/4    R+   21:08   0:00 grep php-fpm
root      6184  0.0  0.1 137724  4440 ?        Ss   16:26   0:00 php-fpm: master process (/usr/local/etc/php-fpm.conf)
nobody    6185  0.0  0.1 137788  5536 ?        S    16:26   0:00 php-fpm: pool www
nobody    6186  0.0  0.1 137788  5536 ?        S    16:26   0:00 php-fpm: pool www

安装nginx

在 centos上,直接 yum install nginx,然后看nginx配置:

  • 主配置: /etc/nginx/nginx.conf
  • 从配置:/etc/nginx/conf.d/default.conf

如果源码编译nginx,执行:

  1. 安装依赖:yum -y install pcre-devel openssl openssl-devel
  2. 编译源码:./configure && make && make install

编辑从配置文件,解除跟 php 相关的配置的注释:

$ vi /etc/nginx/conf.d/default.conf`
#
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#

location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        include        fastcgi_params;
        #include        /etc/nginx/fastcgi_params;   # 等效语句
    }

上述3条指令的意思:

  • fastcgi_pass: 把 *.php结尾的,以fastcgi的方式转发到127.0.0.1:9000;
  • fastcgi_param: 对应的php文件是 /scripts$fastcgi_script_name,其中$fastcgi_script_name是文件名变量,路径是/scripts,也就是说我们的helloworld.php需要放置在/scripts/helloworld.php里。当然目录可以改。
  • include fastcgi_params: 携带fastcgi的参数,其中相对路径fastcgi_params就是/etc/nginx/fastcgi_params,因为配置文件的根路径是/etc/nginx

编写php

$ cat /scripts/helloworld.php
<?php
    phpinfo();
?>

写个php文件,放在 /scripts/helloworld.php

访问php

$ nginx    # 启动nginx
$ curl http://localhost/helloworld.php

参考资料