背景
最近移植 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”
參考資料: