![[排查] 搭建 LEMP 环境常见错误及解决方法(配置文件/权限/服务启动)](https://file.hostol.com/wp-content/uploads/2025/05/LEMP搭建环境-1.png)
嘿,各位 LEMP 勇士们!如果你刚刚跟着我们的《Ubuntu 22.04 从零搭建 LEMP 环境保姆级教程》一步步把 Nginx、MySQL 和 PHP-FPM 这“三巨头”请到了你的服务器上,心里是不是充满了成就感?感觉就像亲手组装了一台高性能的“网站发动机”,就等着它轰鸣启动,大放异彩了!
但是,有时候,即使我们每一步都小心翼翼,这台精密的“机器”也可能因为某个小小的“零件错位”(配置错误)、“线路接触不良”(权限问题)或者“点火失败”(服务启动问题)而无法顺利运转。你可能会遇到:浏览器里看到的还是 Nginx 的欢迎页而不是你的 PHP 应用,访问 PHP 文件直接提示下载或者显示源码,更让人头疼的可能还有 502 Bad Gateway 错误,或者是 PHP 程序哭着喊着说“连接不上数据库”……
遇到这些情况,先别慌,也别急着砸键盘!这就像你刚组装好的乐高千年隼号,发现有几个零件对不上或者灯不亮,是很正常的“调试过程”。LEMP 环境涉及多个组件的协同工作,任何一个环节出点小差错都可能导致整体“罢工”。
这篇“排障指南”,就是你的“LEMP 专属维修工具箱”。我会带你分析在搭建 LEMP 环境后,最常遇到的那些和**配置文件、文件权限、服务启动**相关的“疑难杂症”,并提供清晰的诊断思路和解决方案,帮助你快速找到问题所在,让你的 LEMP “发动机”真正顺畅地跑起来!
核心排查思路:日志、状态、配置“三板斧”
在开始具体排查之前,我们先确立一个通用的“破案”思路,这“三板斧”几乎能应对大部分服务器问题:
- 第一板斧:查看服务状态 (
systemctl status ...
) – 你的“发动机零件”(Nginx, PHP-FPM, MySQL)到底有没有在正常工作?这是最先要确认的。 - 第二板斧:翻阅错误日志 (Error Logs) – 服务器和应用程序通常会把它们遇到的“不爽”和“故障信息”记录在日志里。日志是定位问题的金矿!
- 第三板斧:检查配置文件 (Configuration Files) – 是不是哪个参数写错了?哪个路径指错了?哪个权限没给对?配置文件是所有服务的“行为准则”。
记住这个流程,我们就能更有条理地去“捉虫”了。
常见错误一:Nginx 显示欢迎页或404,而不是我的PHP应用
症状表现:
你信心满满地在浏览器输入你的域名或服务器 IP,结果看到的要么是 Nginx 的默认欢迎页面 (“Welcome to nginx!”),要么是针对你的 index.php
或其他 PHP 文件报 404 Not Found 错误。你的 PHP 应用就像是“隐身”了一样。
“元凶”可能藏在哪里?
- Nginx 网站配置文件 (Server Block) 未正确加载或启用:排查与解决:
- 确认你为网站创建的 Nginx 配置文件(例如
/etc/nginx/sites-available/yourdomain.com
)是否已经通过符号链接正确地放到了/etc/nginx/sites-enabled/
目录下?(使用ls -l /etc/nginx/sites-enabled/
查看)。 - 如果
sites-enabled
目录下还有一个名为default
的链接(指向默认配置),而你的自定义配置没有被优先匹配,它可能会干扰。可以考虑先移除默认配置的链接:sudo rm /etc/nginx/sites-enabled/default
(请先确认你的自定义配置能正常工作)。 - 每次修改或添加了新的网站配置文件后,是否执行了
sudo systemctl reload nginx
或sudo systemctl restart nginx
来让 Nginx 重新加载配置?
- 确认你为网站创建的 Nginx 配置文件(例如
- 配置文件中的
server_name
指令不匹配: Nginx 通过请求头中的 `Host` 字段来匹配哪个server
块应该处理当前请求。如果你的配置文件里server_name
写的是yourdomain.com www.yourdomain.com;
,但你是通过 IP 地址或者一个完全不同的域名访问的,Nginx 可能就匹配不到这个配置块,转而使用了默认的配置(显示欢迎页)。 排查与解决: 确保server_name
指令包含了你访问时使用的所有域名和子域名。如果用 IP 访问测试,可以临时加上服务器的 IP 地址,或者使用_
(下划线)作为通配符(但作为默认 server 才推荐)。 - 配置文件中的
root
指令路径错误:root
指令告诉 Nginx 你的网站文件实际存放在服务器的哪个目录下。如果这个路径写错了,Nginx 自然找不到你的index.php
或其他文件。 排查与解决: 仔细核对root /var/www/yourdomain.com/public_html;
这样的路径是否真实存在,并且你的网站文件确实放在那里。 index
指令中没有index.php
或者顺序不对:index
指令定义了当用户只访问一个目录(比如http://yourdomain.com/
)时,Nginx 应该按什么顺序去查找默认的首页文件。确保index.php
在列表里,并且通常应该放在其他 HTML 文件(如index.html
)的前面,以便优先处理 PHP 首页。 示例:index index.php index.html index.htm;
- PHP 的
location ~ \.php$ { ... }
配置块缺失或有误: 这是让 Nginx 将 PHP 请求传递给 PHP-FPM 的核心配置。如果这个块没有正确配置(比如fastcgi_pass
指向的 PHP-FPM socket 路径错误),Nginx 可能就不知道怎么处理 PHP 文件。 排查与解决: 仔细检查这个location
块是否存在、语法是否正确、fastcgi_pass
是否指向了你当前 PHP 版本正确的 FPM socket 文件路径(如unix:/var/run/php/php8.1-fpm.sock
)。 - Nginx 配置文件语法测试未通过: 在你修改完任何 Nginx 配置后,都应该先用
sudo nginx -t
命令检查一下语法。如果这里有报错,Nginx 可能根本就没能成功加载你的新配置。 排查与解决: 根据nginx -t
的错误提示,修复配置文件中的语法问题,直到测试通过为止,然后再reload
Nginx。 - 查看 Nginx 错误日志:
/var/log/nginx/error.log
(或你站点配置中指定的错误日志路径) 通常会记录下 Nginx 在处理请求时遇到的具体问题,这是排查的第一手资料。
常见错误二:访问PHP文件提示下载,或直接显示PHP源码
症状表现:
你兴致勃勃地在浏览器里输入 http://yourdomain.com/index.php
,结果浏览器没有执行 PHP 代码并显示网页,反而弹出了一个下载框,让你下载 index.php
这个文件!或者更糟,浏览器直接把你的 PHP 源代码(那些 <?php ... ?>
代码)原封不动地显示在了页面上。这可太尴尬了,也太不安全了!
“元凶”可能藏在哪里?
这种情况几乎可以肯定地说:**Nginx 没有把对 .php
文件的请求正确地传递给 PHP-FPM 进行解释执行。** 它把 PHP 文件当成了一个普通的静态文本文件来处理了。
- Nginx 配置文件中处理 PHP 的
location ~ \.php$ { ... }
块配置错误或缺失: 这是最常见的原因。你需要确保你的 Nginx 网站配置文件里有类似下面这样的配置块,并且它是正确且生效的: [提示:请将以下代码片段复制并粘贴到 WordPress 的“代码”区块中]location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # 确保这个路径正确! # 或者如果是 TCP 方式: fastcgi_pass 127.0.0.1:9000; }
排查与解决:- 检查这个
location
块是否真的存在于你启用的网站配置文件中? fastcgi_pass
指令后面的 PHP-FPM 监听地址(是 Unix socket 还是 TCP 端口?)是否和你 PHP-FPM 的实际配置一致?路径或端口号有没有写错?include snippets/fastcgi-php.conf;
这一行是否正确?这个文件里通常包含了将请求参数传递给 PHP 的重要设置。- 有没有可能这个
location
块被其他更优先的location
规则覆盖了?(Nginx location 匹配顺序比较复杂,需要注意)
- 检查这个
- PHP-FPM 服务未运行或监听配置错误: 即使 Nginx 配置了正确的
fastcgi_pass
,但如果 PHP-FPM 服务本身就没启动,或者它监听的 socket 文件/TCP端口与 Nginx 配置的不一样,Nginx 照样“找不到人”。 排查与解决:- 用
sudo systemctl status php8.1-fpm
(替换为你的版本) 检查 PHP-FPM 服务是否正常运行。 - 查看 PHP-FPM 的 `pool` 配置文件 (通常在
/etc/php/8.1/fpm/pool.d/www.conf
),找到listen = ...
这一行,确认它监听的地址(是/var/run/php/php8.1-fpm.sock
还是127.0.0.1:9000
?)与 Nginx 配置中的fastcgi_pass
完全一致。 - 检查 PHP-FPM 的错误日志 (路径通常在其 `pool` 配置文件中定义,或者查看系统日志 `journalctl -u php8.1-fpm`),看看是否有启动失败或运行错误的信息。
- 用
- (较少见) Nginx 缺少处理 PHP 的 MIME 类型配置: 虽然 Nginx 默认通常能识别
.php
文件,但如果因为某些原因 MIME 类型配置 (mime.types
文件或types {}
指令) 出了问题,也可能导致它不把 PHP 文件当成可执行脚本。不过这种情况比较罕见。
当你遇到 PHP 文件被下载或源码泄露时,请第一时间把“怀疑的目光”投向 Nginx 配置文件里那个专门伺候 PHP 的 location ~ \.php$
块,以及 PHP-FPM 服务的运行状态和监听配置!
常见错误三:Nginx 报 502 Bad Gateway
啊哈,又是这个“老朋友”!我们在之前的《解决 Nginx 502 Bad Gateway 错误的常见原因与步骤》(请替换为实际链接)一文中已经详细剖析过它了。502 错误意味着 Nginx 作为网关,在尝试从上游(也就是我们的 PHP-FPM)获取响应时,收到了一个无效的响应,或者连接被拒绝/重置。
在 LEMP 环境中,导致 Nginx 针对 PHP-FPM 报 502 的常见原因主要有:
- PHP-FPM 服务未运行或已崩溃。 (用
systemctl status phpX.X-fpm
检查) - Nginx 配置的
fastcgi_pass
指向的 PHP-FPM socket 文件路径错误或不存在。 - PHP-FPM 的 socket 文件权限问题,导致 Nginx 运行用户 (通常是
www-data
) 没有权限访问它。 (用ls -l /var/run/php/phpX.X-fpm.sock
检查权限,并确认 PHP-FPM pool 配置文件中listen.owner
和listen.group
设置是否与 Nginx 用户匹配,或者 socket 权限是否允许 Nginx 用户访问)。 - PHP-FPM 工作进程池 (pool) 配置不当,比如
pm.max_children
(最大子进程数)设置过低,导致在高并发时没有足够的 FPM 进程来处理 Nginx 转过来的请求,Nginx 连接 FPM 时被拒绝或超时。 (检查 PHP-FPM 日志) - PHP 脚本自身执行出错并异常终止,导致 PHP-FPM 进程崩溃,从而使 Nginx 收不到有效响应。 (需要查看 PHP 错误日志和应用日志)
- 服务器资源耗尽(如内存不足导致 OOM Killer 杀掉了 PHP-FPM 进程)。
排查思路: 强烈建议您回顾我们专门讨论 Nginx 502 的那篇文章,里面的排查步骤同样适用于 LEMP 环境下的 PHP-FPM 问题。核心就是:检查 PHP-FPM 服务状态 -> 检查 Nginx 错误日志中关于 upstream 的具体报错信息 -> 检查 Nginx 配置中 fastcgi_pass
的正确性 -> 深入分析 PHP-FPM 的错误日志和 PHP 脚本本身的错误日志。
常见错误四:PHP 应用无法连接到 MySQL/MariaDB 数据库
症状表现:
你的网站页面可能直接显示“数据库连接错误”(比如 WordPress 著名的 “Error establishing a database connection”),或者在 PHP 错误日志中看到类似 `PDOException: SQLSTATE[HY000] [2002] No such file or directory` (连接 socket 失败) 或 `SQLSTATE[HY000] [1045] Access denied for user …` (用户认证失败) 或 `SQLSTATE[HY000] [2003] Can’t connect to MySQL server on ‘…’` (网络连接失败) 的错误信息。
“元凶”可能藏在哪里?
- MySQL/MariaDB 服务未运行: 排查与解决: 用
sudo systemctl status mysql
(或mariadb
) 检查服务状态,如果没运行就启动它。 - 应用程序中的数据库连接凭证错误: 你的 PHP 应用(比如 WordPress 的
wp-config.php
文件,或者其他框架的数据库配置文件)里填写的数据库主机名 (DB_HOST)、数据库名 (DB_NAME)、数据库用户名 (DB_USER)、数据库密码 (DB_PASSWORD) 是不是写错了? 排查与解决: 仔仔细细核对这些连接参数!- 如果数据库和 PHP 应用在同一台服务器上,
DB_HOST
通常应该是localhost
或127.0.0.1
。 - 确保数据库名、用户名、密码与你在 MySQL/MariaDB 中实际创建的完全一致(大小写敏感!)。
- 如果数据库和 PHP 应用在同一台服务器上,
- 数据库用户权限问题: 你在应用中使用的那个数据库用户,是否真的被授予了访问对应数据库的权限?并且它是否允许从你 PHP 应用连接过来的主机(通常是
localhost
)进行连接? 排查与解决: 登录 MySQL (sudo mysql -u root -p
),执行SHOW GRANTS FOR 'your_app_user'@'localhost';
(替换为你的应用用户名和连接主机) 查看权限。如果没有权限,需要用GRANT
语句授权。 - MySQL/MariaDB 未监听本地连接或监听地址/端口错误: 如果你的应用通过
localhost
或127.0.0.1
连接,需要确保 MySQL/MariaDB 在其配置文件 (my.cnf
) 中的bind-address
设置为127.0.0.1
(或者0.0.0.0
,但不推荐,除非配合严格防火墙),并且监听的端口 (默认 3306) 正确。 排查与解决: 用sudo ss -tlpn | grep ':3306'
检查 MySQL 是否在监听127.0.0.1:3306
或*:3306
。 - PHP 的 MySQL 扩展未安装或未启用: PHP 需要特定的扩展(如
php-mysql
或php-mysqli
,php-pdo_mysql
)才能和 MySQL/MariaDB 数据库通信。我们在第四步安装 PHP 时已经包含了php8.1-mysql
,但如果你使用的是其他 PHP 版本或自定义安装,需要确认这个扩展已正确安装并启用。 排查与解决: 在你的测试文件info.php
的输出中,搜索 “mysql”, “mysqli”, “pdo_mysql” 等关键字,看看相关模块是否已加载。或者在命令行执行php -m | grep mysql
。 - Socket 与 TCP/IP 连接方式的混淆: 当 PHP 连接配置中的主机名是
localhost
时,很多 PHP 数据库驱动会默认尝试通过 Unix socket 文件(而不是 TCP/IP)去连接 MySQL。如果 MySQL 服务器配置的 socket 文件路径与 PHP 期望的路径不一致(可以在php.ini
中查看pdo_mysql.default_socket
或mysqli.default_socket
),就可能报类似SQLSTATE[HY000] [2002] No such file or directory
的错误。或者,如果 MySQL 根本就没配置使用 socket(比如只监听了 TCP 端口),也会失败。 排查与解决: 确保 MySQL 和 PHP 的 socket 配置一致。一个简单的解决方法是,在 PHP 的数据库连接配置中,将主机名从localhost
明确改为127.0.0.1
,这样通常会强制 PHP 使用 TCP/IP 方式进行连接,从而绕开 socket 路径问题。
数据库连接不上时,务必仔细查看 PHP 错误日志和 MySQL/MariaDB 错误日志,它们通常会给出非常具体的错误原因。
常见错误五:文件/目录权限问题导致 403 Forbidden 或应用写入失败
症状表现:
浏览器访问你的网站或特定页面时,Nginx 返回一个 403 Forbidden
错误,告诉你“禁止访问!”。或者,你的 PHP 应用程序(比如 WordPress)在尝试上传文件、创建缓存目录、或者写入日志文件时失败了,并在应用日志中报错(通常是“Permission denied”)。
“元凶”可能藏在哪里?
这几乎总是由于 **Linux 文件系统的权限和所有权设置不正确**导致的。Nginx 进程和 PHP-FPM 进程(它们通常都以一个特定的低权限用户运行,比如 www-data
或 nginx
)没有足够的权限去读取你的网站文件,或者没有权限在你应用需要写入的目录里进行写操作。
- 网站根目录及其下文件的所有权 (Ownership) 不正确: 你的网站文件 (
/var/www/yourdomain.com/public_html
及其内部所有文件和子目录) 的所有者和所属组,应该是 Nginx/PHP-FPM 运行的那个用户(通常是www-data
)。如果所有者是你自己的普通用户账号,那么www-data
可能就没权限读取。 修复步骤: 使用chown
命令递归地修改所有权: [提示:请将以下代码片段复制并粘贴到 WordPress 的“代码”区块中]sudo chown -R www-data:www-data /var/www/yourdomain.com/public_html
- 文件和目录的权限模式 (Permissions Mode) 不正确: 即使所有权对了,权限模式不对也不行。
- 目录 通常需要
755
(drwxr-xr-x
) 权限,这意味着所有者可读可写可执行(进入),所属组和其他用户可读可执行。这能保证 Nginx/PHP-FPM 能进入目录并列出文件。 - 文件 通常需要
644
(-rw-r--r--
) 权限,意味着所有者可读可写,所属组和其他用户只读。这能保证 Nginx/PHP-FPM 能读取文件内容。 - 对于那些**需要被 PHP 脚本写入的特定目录**(比如 WordPress 的
wp-content/uploads
目录,或者各种缓存目录),除了所有权是www-data
外,权限可能需要设置得更宽松一些,比如让所有者 (www-data
) 或所属组 (www-data
) 拥有写权限 (例如目录775
,文件664
,或者更精确地只给www-data
用户写权限)。
chmod
命令修改权限: [提示:请将以下代码片段复制并粘贴到 WordPress 的“代码”区块中]# 设置所有目录为 755 sudo find /var/www/yourdomain.com/public_html -type d -exec chmod 755 {} \; # 设置所有文件为 644 sudo find /var/www/yourdomain.com/public_html -type f -exec chmod 644 {} \; # 然后再针对需要写入的目录单独设置更宽松的权限 (需谨慎) # 例如:sudo chmod -R g+w /var/www/yourdomain.com/public_html/wp-content/uploads
- 目录 通常需要
- Nginx 配置中
autoindex off;
且目录下没有默认首页文件: 如果你访问的是一个目录 URL(比如http://yourdomain.com/images/
),而 Nginx 配置中禁止了目录列表显示 (autoindex off;
是默认且推荐的),并且这个目录下又没有 Nginx 能识别的首页文件(如index.html
,index.php
),Nginx 可能会返回 403 Forbidden。 修复步骤: 确保目录下有首页文件,或者在 Nginx 配置中为这个 location 开启autoindex on;
(不推荐用于公网)。 - (较少见) SELinux 或 AppArmor 策略阻止: 如果你的系统强制开启了 SELinux 或 AppArmor,它们的安全策略也可能阻止 Nginx 或 PHP-FPM 访问特定的文件或目录,即使传统的 Unix 权限看起来是正确的。你需要检查相关的安全日志 (如
/var/log/audit/audit.log
) 并调整策略。
文件权限问题是 LEMP 环境中新手最容易犯错的地方之一,务必仔细检查!
结论:耐心调试,LEMP 皆可驯服
搭建 LEMP 环境,就像是组装一台精密的机器,Nginx、MySQL、PHP-FPM 这三个核心部件,再加上 Linux 这个平台,每一个环节的配置、每一个组件之间的“握手”,都需要精确无误。初次尝试时遇到一些错误和不顺,是非常正常的,千万不要因此而气馁!
解决这些问题的关键在于:
- 理解原理: 明白每个组件是干什么的,它们之间是如何交互的。
- 善用工具: 学会查看服务状态 (
systemctl status
),分析日志文件 (Nginx error/access log, PHP-FPM log, MySQL error log, system log),使用诊断命令 (nginx -t
,ss
,lsof
)。 - 系统排查: 遵循“从外到内”(网络->Nginx->PHP-FPM->MySQL->应用代码)、“从现象到本质”的逻辑,一步步缩小问题范围。
- 细心与耐心: 仔细核对配置文件中的每一个路径、每一个端口号、每一个权限设置。
希望这篇针对 LEMP 环境常见错误的排查指南,能成为你手中的“万能扳手”,在你遇到问题时,帮助你快速定位并修复故障。只要你多动手、多思考、多总结,再复杂的“机器”也能被你驯服!
还有疑问?常见问题解答 (FAQs)
- 问: 除了 Nginx, PHP-FPM, MySQL 的日志,还有哪些日志对排查 LEMP 环境问题特别重要? 答: 除了这三个核心组件的专用日志外,Linux 系统的**通用日志**也非常关键。在 Ubuntu/Debian 上,主要是
/var/log/syslog
和/var/log/auth.log
;在 CentOS/RHEL 上,主要是/var/log/messages
和/var/log/secure
。syslog
/messages
会记录很多系统级的事件和错误,比如内核消息、OOM (Out Of Memory) Killer 的活动、磁盘问题等。auth.log
/secure
则记录所有认证相关的尝试,比如 SSH 登录、sudo 使用等,有助于发现安全问题或权限问题。对于使用 systemd 的系统,journalctl
命令是查看所有系统和服务日志的强大统一入口 (例如journalctl -u nginx -n 50 --no-pager
查看 Nginx 最近50条日志)。 - 问: 如何知道我的 PHP 安装了哪些扩展模块?如果缺少某个模块导致应用报错怎么办? 答: 最简单的方法是创建一个包含
<?php phpinfo(); ?>
的 PHP 文件(比如我们测试用的info.php
),通过浏览器访问它,在输出页面中会列出所有已加载的 PHP 模块及其配置信息。或者,在服务器命令行执行php -m
命令,它会列出所有已编译和启用的模块。如果你发现应用需要的某个模块(比如gd
用于图像处理,curl
用于 HTTP 请求,pdo_mysql
用于数据库连接)没有被加载,你可以使用sudo apt search php8.1-模块名
(将 8.1 替换为你的 PHP 版本) 来查找对应的安装包名,然后用sudo apt install 包名
来安装。安装后通常需要重启 PHP-FPM 服务 (sudo systemctl restart php8.1-fpm
)。 - 问: 我执行
sudo nginx -t
测试配置时,提示 “emerg” 或 “crit” 级别的错误,但 Nginx 好像还能勉强运行,可以忽略吗? 答: 绝对不能忽略!nginx -t
报告的 “emerg” (紧急) 或 “crit” (严重) 级别的错误,通常意味着 Nginx 的核心配置存在严重问题,或者无法绑定到指定的端口/IP,或者无法加载必要的模块。即使 Nginx 可能看起来还在运行(比如旧的 worker 进程还在处理请求),但它很可能无法正确加载新的配置,或者在下次重启后会彻底失败。你必须根据错误提示,修复配置文件中的问题,直到nginx -t
显示 “syntax is ok” 和 “test is successful” 为止,然后再执行sudo systemctl reload nginx
或restart
。 - 问: 我的 PHP 脚本执行起来非常慢,是不是 LEMP 环境配置的问题?该如何优化? 答: PHP 脚本执行缓慢的原因可能有很多,LEMP 环境配置只是其中一部分。你需要系统地排查:1) PHP 代码本身: 是否存在低效算法、过多循环、或者阻塞式的外部调用?使用 Xdebug 等工具进行性能剖析。2) PHP-FPM 配置:
pm
(进程管理器) 的设置是否合理(static
,dynamic
,ondemand
)?pm.max_children
,pm.start_servers
等参数是否与你的服务器资源和并发量匹配?OPcache 是否开启并合理配置?3) MySQL 查询性能: 是否有慢查询?索引是否缺失?数据库服务器本身是否成为瓶颈?4) Nginx 配置: 虽然 Nginx 本身很快,但错误的 FastCGI 参数配置也可能影响通信效率。5) 服务器资源: CPU、内存、磁盘 I/O 是否充足?优化是一个系统工程,需要逐个环节分析。通常,应用代码和数据库查询是最大的优化点。 - 问: 如何为我的 LEMP 网站启用 HTTPS (SSL证书)? 答: 为网站启用 HTTPS 是现代网站的标配。最简单、最经济的方式是使用 Let’s Encrypt 提供的免费 SSL 证书,并配合 Certbot 工具来自动化证书的申请、配置和续期。