Ubuntu Linode 上 Nginx 的 PHP 错误(通过 FastCGI)

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),因为我遵循的指南使用了某种守护进程。

非常感谢您给予我的任何帮助。

答案1

简短回答:

最可能的情况是,您在 Nginx 中存在轻微配置错误,导致将错误路径发送到 PHP-FPM。确保您的 root 指令位于位置块之外,打开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 的详细程度增加到“notice”——我想查看可能出现的任何问题
  • 我已经指定了一个 access_log - 我希望能够确认我尝试访问的任何文件都会显示在 access_log 或 error_log 中 - 没有任何未说明的内容。

将“test.txt”复制到“/srv/www/mysite.com/public_html”,确保用户“nginx”(nginx 默认以该用户身份运行)可以读取该文件,644 的权限应该足够。确保 public_html 上的所有目录对“other”都具有“执行”权限(即“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 ~ \.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 指令直接包含在位置块中 - 但我发现,当您获得更复杂的设置时,拥有外部文件会更易于维护。您会在这里注意到,路径取决于 $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 错误日志,此时您应该已经记录了足够多的信息来识别问题。

相关内容