背景
最近移植 apache2.4 + php5 到 H3 ,一般是apache 支持 php 是通过mod_php 方式的,即需要
LoadModule php5_module modules/libphp5.so
但是要编译出 给apache 用的 libphp5.so 的话,编译 php5 时需要 configure 指定 --with-apxs2 = /usr/local/httpd/apache/bin/apxs 参数,但是在交叉编译的情况下apxs 是无法运行的,所以无法编译出 libphp5.so 。除非放到H3板子上进行编译,那样的话肯定不妥!
——那还有什么办法可以让 apache 支持 php 吗? 有的。
Sapi通过通过一系列的接口,使得外部应用可以和PHP交换数据并可以根据不同应用特点实现特定的处理方法,我们常见的一些sapi有:
apache2handler:这是以apache作为webserver,采用mod_PHP模式运行时候的处理方式,也是现在应用最广泛的一种。
cgi:这是webserver和PHP直接的另一种交互方式,也就是大名鼎鼎的fastcgi协议,在最近几年fastcgi+PHP得到越来越多的应用,也是异步webserver所唯一支持的方式。
cli:命令行调用的应用模式
apache 与 php 的关系
apache 是一个webserver ,主要工作是接收请求,返回数据,本身不具备解析.php 文件的能力,这就需要借助 mod_php 或者 使用 cgi 协议与 php 解析进程进行数据交互。
php-fpm 的作用
实现fastcgi 协议,解析.php 文件,并返回解析后的内容。
(可以理解为 fastcgi 协议 是cgi 协议的改良版)
php-fpm 的编译
From release 5.3.3 onwards, PHP now includes the fastCGI process manager (php-fpm) in the stock source code.
Your distribution or OS will either include it in the stock PHP package, or make it available as an add-on package; you can build it from source by adding --enable-fpm to your ./configure options.
./configure 的时候添加 --enable-fpm 选项,就能编译出php-fpm。
php-fpm 的启动脚本
/etc/init.d/php5-fpm
常用启动方法(默认开机启动)
/etc/init.d/php5-fpm start
/etc/init.d/php5-fpm restart
/etc/init.d/php5-fpm stop
查看是否启动成功:ps | grep php-fpm
ps | grep php-fpm
3072 root 96272 S php-fpm: master process (/etc/php5-fpm.conf)
3073 nobody 96272 S php-fpm: pool www
3074 nobody 96272 S php-fpm: pool www
3224 root 3080 S grep php-fpm
php-fpm 的配置文件
/etc
├── php5-fpm.conf
├── php5-fpm.d
│ └── www.conf
├── php.ini
配置修改要点:
- www.conf
注意 user group 要与 apache 的 httpd.conf 中的一致[www] user = nobody group = nogroup listen = 127.0.0.1:9000 listen.owner = nobody listen.group = nogroup listen.mode = 0666 pm = dynamic
apache 端配置
httpd.conf
修改要点:
-
mpm 需要改成 event 模式
# LoadModule mpm_prefork_module modules/mod_mpm_prefork.so #LoadModule mpm_worker_module modules/mod_mpm_worker.so LoadModule mpm_event_module modules/mod_mpm_event.so
-
确保启用了 mod_proxy_fcgi
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
-
添加支持 index.php
DirectoryIndex index.html DirectoryIndex index.php
-
添加 vhost 并 使用 ProxyPassMatch
<VirtualHost *:80> ServerAdmin [email protected] DocumentRoot "/usr/share/htdocs" ServerName localhost <Directory "/usr/share/htdocs"> Options None Require all granted </Directory> ProxyRequests Off ProxyPassMatch "^/(.*\.php(/.*)?)$" "fcgi://127.0.0.1:9000/usr/share/htdocs/$1" </VirtualHost>
注意 ProxyPassMatch “^/(.*\.php(/.*)?)$” “fcgi://127.0.0.1:9000/usr/share/htdocs/$1” 中的
127.0.0.1:9000 后面的路径要与 DocumentRoot 一致。
其作用大致是 所有以 .php 结尾的请求都转发给 127.0.0.1:9000 ,php-fpm 会一直监听127.0.0.1:9000,并解析.php 文件。
测试验证
在 /usr/share/htdocs 下写一个index.php 用最简单的phpinfo()函数。
<?php
phpinfo();
?>
并将原来的index.html 改名或者删掉:
# ls /usr/share/htdocs/
index.hide index.php
打开浏览器输入ip 地址,正常的话可以打开看到这样的页面。
遇到的问题:
无法打开页面,查看/var/log/error_log
AH01071: Got error 'Unable to open primary script: /usr/share/htdocs/index.php (No such file or directory)\n’
找不到文件?
网上找了很多资料,大多都是说只要保证 ProxyPassMatch 那行 127.0.0.1:9000 后的路径地址与DocumentRoot 一致,www.conf 里的 user group 要与http.conf 中的一致就可以了。可是我的就是不行!
最终我无意中发现吧 index.php 放到 /www 里,OK 了!这是为什么呢?
“fcgi://127.0.0.1:9000/usr/share/htdocs/index.php” 最终却是要读取/www/index.php ? 这是个什么奇怪的设定?
查找相关设置发现 在php.ini 中设置了 doc_root = “/www” ,
有两种解决方法:
- 方法1.建立软连接 /www 指向 /usr/share/htdocs
ln -sf /usr/share/htdocs /www - 方法2. 直接改 doc_root
php.ini 中的
doc_root = “/www”
改为
doc_root = “/usr/share/htdocs”
参考资料: