502錯誤,讓你進一步明白nginx和php-fpm之間的關係
ofollow,noindex">《什麼是SAPI,FastCGI,PHP-FPM?學習PHP的必備知識》 這篇文章講解了一些基礎知識,寫這篇文章的根本原因是自己在部署Nginx+PHP-FPM的時候遇到了二個問題。今天我就回顧下當時遇到的一個502錯誤(另外一個問題有機會再講),以及最後的解決方法,大家也別小看這個502錯誤,充分理解非常必要,希望通過這篇文章大家能夠學到一些知識。
在我這個案例中,Nginx通過FastCGI協議連線PHP-FPM(7.1),Nginx和PHP-FPM部署在同一臺機器上,配置完成後,在瀏覽器中訪問,報了一個 502 錯誤。
首先引用下百科對於 502 的介紹:
The server was acting as a gateway or proxy and received an invalid response from the upstream server.
它的意思就是Nginx沒有獲取到PHP-FPM的響應。
我當時處理的比較著急,花了很久的時間,此處忽略各種的排查過程,先貼下最後正確的配置(和本次問題有關的)。
(1)nginx.conf:
error_loglogs/error.log; user www-data www-data;
(2)php-fpm.conf:
access.log = /var/log/fpm.log
(3)pool.d/www.conf (PHP-FPM pool 配置檔案):
user = www-data group = www-data listen = /run/php/php7.1-fpm.sock listen.owner = www-data(錯誤產生時的配置:listen.owner = www) listen.group = www-data(錯誤產生時的配置:listen.owner = www) listen.mode = 0660 access.log = /var/log/fpm-www.access.log
再解釋下 pool 配置檔案,一般情況下,nginx 一個虛擬主機對應一個 php-fpm pool 檔案,這樣不同的 php-fpm 工作程序就隔離了,互不影響。
接下去介紹分析過程:
1:在出現 502 問題的時候,觀察 nginx 的 error.log 檔案,會有以下報錯:
2018/09/18 18:34:32 [crit] 2831#0: *493 connect() to unix:/run/php/php7.1-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 18.179.21.152, server: www.simplehttps.com, request: "GET /1.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.1-fpm.sock:", host: "www.simplehttps.com"
其實說的已經很明白了,連線 PHP-FPM 的時候遇到了許可權問題。
2:觀察下 php 主程序的 error.log
發現 /var/log/fpm.log 檔案沒有任何的輸出,查閱了官方資料,對於 error_log 這個指令解釋的非常少。
我猜測有兩種作用:
- 每個 pool 的錯誤會重定向到這個檔案中。(經過測試,pool錯誤和這個檔案沒有關係)
- PHP-FPM 主程序的一些控制錯誤。(從本案例來說,主程序並不知道Nginx遇到了錯誤,所以也沒有錯誤輸出)
最後,php-fpm.conf 下的 error_log 指令在我看來沒有任何的實際用處,如果讀者有知道的,歡迎指導。
(3)定位問題
知道了nginx通過本地socket方式連線php-fpm遇到許可權問題,定位到了listen.owner和 listen.group指令。
產生問題的原因就是nginx程序的屬主和php-fpm屬主許可權不一樣,在發生502問題的時候,nginx屬主是www-data,而listen.owner是www。把它們修改一致後,問題解決。
我們不禁要問,listen.owner和listen.group指令表示什麼?看官方的介紹:
; Set permissions for unix socket, if one is used. In Linux, read/write ; permissions must be set in order to allow connections from a web server. Man y
它們表示php-fpm工作程序以unix socket和web伺服器連線的時候,該socket的許可權必須和web伺服器的操作(讀取)許可權一致。
讀者大概明白了什麼意思,那user和group這兩個指令什麼意思,為什麼和listen.owner指令如此相像,官方是這麼介紹的:
; Unix user/group of processes
解釋的不是很清楚,實際上表明的是這個php-fpm程序本身許可權(通過 ps aux | grep php-fpm就能進一步確認),如果php-fpm要傳遞錯誤資料給nginx,那麼user和group的指令必須和nginx的user指令配置一樣(以後會寫文章說明)。
這也間接說明了,如果nginx的user指令和php-fpm工作程序的listen.user指令配置不一樣,也不影響兩者互動。只是在本機中,nginx和php-fpm如果要讀取或操作同一檔案,需要配置一致,關於這一點希望大家仔細體會。
實際上最簡單的解決方案,就是通過tcp的方式連線nginx和php-fpm(即www.conf 配置listen = 127.0.0.1:9000),這樣不會有許可權操作的問題,但對於本機來說,socket連線相比tcp連線,速度上更有保證。
【本文2018/09/19 發表於https://mp.weixin.qq.com/s/keJuNwnZu2ejnZqCvXxy3A ,也可以關注我的新書《深入淺出HTTPS:從原理到實戰》 】