Ubuntu Linode 上 Nginx 的 PHP 錯誤(通過 FastCGI)
我使用以下指南在 Linode 的 Ubuntu 10.04 伺服器上設置 LEMP(Linux、Nginx、MySQL 和 PHP):http: //library.linode.com/lemp-guides/ubuntu-10.04-lucid
本質上,我將我的 PHP 腳本上傳到
/srv/www/mysite.com/public_html
了/etc/nginx/sites-available/mysite.com.conf
.在瀏覽器中訪問該站點會給我一個 500 內部伺服器錯誤。我假設 PHP 程式碼有一些錯誤,這很好。但是,我完全不知道如何調試它,因為有幾個組件:PHP、FastCGI 和 Nginx。
我的問題是,如何讓這些錯誤顯示在瀏覽器中,或者至少顯示在日誌中,以便我可以弄清楚發生了什麼?我不確定是否需要告訴 Nginx 在某處記錄錯誤、FastCGI 或編輯 php.ini。
我對伺服器具有完全的 root 訪問權限來解決這個問題。但是,我不確定如何重新啟動 PHP/FastCGI(儘管我知道如何重新啟動 Nginx),因為我遵循的指南使用了某種守護程序。
非常感謝您能給我的任何幫助。
簡短的回答:
最有可能的情況是您在 Nginx 中有輕微的配置錯誤,導致發送到 PHP-FPM 的路徑不正確。確保您的根指令位於 location 塊之外,打開
fastcgi_intercept_errors
,增加您的 error_log 的詳細程度(例如注意)並查閱這些日誌以獲取更多資訊。長答案 - 診斷問題
首先,我不是一個 Ubuntu 的人(更像是一個 CentOS 的人)——所以如果一些路徑/包對你的作業系統沒有那麼理想,你會原諒我的。
正如您所說,您的設置中有多個必須協同工作的部分。
- Nginx - 必須能夠接收和處理請求 - 最簡單的測試是靜態文件。
- FastCGI - 必須能夠與 PHP 通信。
- PHP - 必須能夠成功解釋您的文件。
對於這種診斷方法,我們希望保持簡單——不要通過嘗試載入像 Wordpress 這樣的 CMS 來測試它——我們需要一個獨立的文件。
測試文件:
靜態 - 讓我們使用一個名為“test.txt”的文本文件。
測試.txt:
Hello world
PHP - 讓我們使用 phpinfo() 函式。
測試.php:
<?php phpinfo(); ?>
測試 Nginx:
如果 Nginx 可以提供靜態文件,我們可以確認基本設置和軟體功能正常。
server { listen *:80 default; server_name mysite.com www.mysite.com; root /srv/www/mysite.com/public_html; error_log /var/log/nginx/mysite.com/error.log notice; access_log /var/log/nginx/mysite.com/access.log main; }
提幾點:
- 我在監聽行中添加了“預設”——這有望確保使用該伺服器塊(當然,除非您有其他指定“預設”的伺服器塊,這是一個不同的問題)。
- 我已將 error_log 的詳細程度增加到“通知” - 我想查看可能出現的任何問題
- 我指定了 access_log - 我希望能夠確認我嘗試訪問的任何文件都顯示在 access_log 或 error_log 中 - 沒有任何原因。
將’test.txt’複製到’/srv/www/mysite.com/public_html’,確保使用者’nginx’(這是nginx執行的預設使用者)可讀,644的權限應該足夠了。確保public_html之上的所有目錄對’other’都有’execute’權限(即’other’可以遍歷目錄結構)。
重新啟動 Nginx 以使配置更改生效(如果需要,您可以重新載入而不是重新啟動)。
從您安裝了 nginx 的同一台伺服器上進行測試:
curl --header "Host: mysite.com" 127.0.0.1/test.txt
這裡值得注意的點:
- 通過在設置了 nginx 的同一台伺服器上進行測試,我們能夠消除 DNS 和網路問題。
- 127.0.0.1 當然是 ’localhost’ (但 ’localhost’ 確實需要在 hosts 文件中指定才能工作)
- 由於我們通過 IP 地址訪問該站點,因此我們應該告訴伺服器我們嘗試訪問的“域名”(此處並非嚴格要求,因為我們將伺服器塊設置為“預設”,但這是一種很好的做法)。
- 最後,我們需要指定文件的路徑——相對於我們的根指令(來自我們的伺服器塊)。
理想情況下,上述命令將返回“Hello world”——您在文本文件中輸入的文本。
PHP:
確保 PHP 正常工作相當容易:
在您的 public_html 文件夾中創建文件“test.php”(如上)並執行:
php /srv/www/mysite.com/public_html/test.php
您應該得到一個長輸出,其中包含您通常在 phpInfo() 頁面上看到的所有資訊。
如果上述方法不起作用:
- 如果您收到某種文件未找到錯誤,請指定 php 的絕對路徑,並檢查文件的路徑
- 如果您收到權限錯誤,請確保您的目前使用者具有所需的權限 - php 在以這種方式訪問時實際上並不需要文件的執行權限。
- 打開
display_errors
並增加 php.ini 文件中 error_reporting 的詳細程度(首先,使用 找到正確的 php.ini 文件php -i | grep 'Loaded Configuration'
)希望現在您已經確認 PHP 和您的簡單測試文件可以正常工作。
PHP-FPM:
不幸的是,FastCGI 不會“說出”純文字。我們需要一名口譯員來幫助我們。你需要
cgi-fcgi
二進製文件。(在 CentOS 上,它可以在來自 EPEL 的包 ‘fcgi’ 中獲得;我相信 Ubuntu 有一個libfcgi
提供相同功能的包)。
cgi-fcgi
讀取環境變數並將正確的請求傳遞給我們的 FastCGI 程序管理器 (PHP-FPM)。首先,讓我們設置 PHP-FPM:預設的全域選項應該就足夠了,但是,啟用日誌記錄 - 調試時,我們需要盡可能多的資訊(預設日誌前綴是 /var)。
error_log = log/php-fpm.log log_level = notice
設置一個基本池,指定:
[www] listen = 127.0.0.1:9000 listen.allowed_clients = 127.0.0.1 pm = dynamic pm.max_children = 5 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 2 user = nginx group = nginx
(當然,您可以 - 並且可能應該使用套接字而不是 TCP 偵聽器,但我發現這種方法更容易測試(即更少的權限問題) - 顯然,確保在您選擇的埠上沒有其他任何東西在監聽)。我們只需要允許本地機器訪問它,設置流程管理器的基礎知識,並給池一個所有者(當然,您稍後會根據您的需要進行更改)。
啟動 PHP-FPM(解決啟動時遇到的任何錯誤)
- FPM 是 PHP 的 FastCGI 程序管理器,它是一個執行的單獨服務 - 通常
service php-fpm restart
可以工作(reload
如果您需要在生產環境中執行此操作,請使用)。(/etc/init.d 中可能有它的初始化腳本)如果你還沒有安裝 cgi-fcgi
執行以下命令:
SCRIPT_NAME=/test.php \ SCRIPT_FILENAME=/srv/www/mysite.com/public_html/test.php \ QUERY_STRING= \ REQUEST_METHOD=GET \ cgi-fcgi -bind -connect 127.0.0.1:9000
在這裡,我們告訴 PHP-FPM 文件的路徑、文件名以及請求類型 (GET),然後指示 cgi-fcgi 連接到正確的主機和埠。
它應該返回與之前相同的輸出,但是這一次,它沒有直接使用 php 二進製文件,而是使用了 FastCGI。如果這可行,則您已成功驗證設置的每個組件。
如果您收到錯誤,請在 /var/log/php-fpm.log 檢查您的錯誤日誌
放在一起: 如果設置的每個部分都有效,那麼,您需要確保所有部分都可以一起工作。真的,這裡只剩下一個部分——讓 Nginx 通過 FastCGI 進行通信。
以最簡單的形式,我們只需要向現有的 nginx 伺服器塊添加一個 location 塊:
location ~ \.php { include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; }
為了支持這一點,文件“fastcgi_params”是相當重要的。真正重要的幾行是:
fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
實際上,您可以將所需的 FastCGI 指令直接包含在 location 塊中 - 但我發現當您進行更複雜的設置時,擁有外部文件更容易維護。您會注意到,路徑取決於 $document_root - 如果您沒有正確設置(根指令),在您的位置塊之外,您通常會遇到設置問題。
某些設置可能還需要一行,例如:
fastcgi_split_path_info ^(.+\.php)(/.+)$;
調試 FastCGI 設置錯誤的一個有用指令是
fastcgi_intercept_errors On
. 這會讓 nginx 記錄錯誤(例如找不到文件等)。最後,嘗試通過 nginx 載入您的 PHP 頁面:
curl --header "Host: mysite.com" 127.0.0.1/test.php
希望你得到你的 phpinfo() 輸出。如果沒有,您知道問題出在您的 nginx 設置中(因為每個其他組件都獨立工作)開始檢查您的 nginx 錯誤日誌,此時您應該記錄了足夠多的資訊來辨識問題。