我按照以下指南在 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 中可能有一个它的初始化脚本)
- FPM 是 PHP 的 FastCGI 进程管理器,它是一个单独运行的服务 - 通常
- 如果还没有安装 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 错误日志,此时您应该已经记录了足够多的信息来识别问题。