Linux

Ubuntu Linode 上 Nginx 的 PHP 錯誤(通過 FastCGI)

  • August 29, 2013

我使用以下指南在 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 錯誤日誌,此時您應該記錄了足夠多的資訊來辨識問題。

引用自:https://serverfault.com/questions/359399