Nginx 故障排除:解决 Web 服务器问题的常用命令行方案
使用实用的 Nginx 命令行检查服务状态、配置错误、日志、端口以及常见的 4xx 或 5xx 故障。
Nginx 故障排除:解决 Web 服务器问题的常用命令行方案
当 Nginx 出现故障时,最初的几分钟通常用于缩小问题范围。是服务停止了?配置更改失败?其他进程已在使用端口 80?Nginx 正常运行但上游应用宕机?如果按正确顺序执行检查,命令行可以快速给出答案。
我倾向于从破坏性最小的命令开始:检查状态、测试配置、读取日志,然后才重新加载或重启。重启可能会隐藏有用的证据,因此只有在了解问题所在后才将其作为修复手段。
基本 Nginx 管理命令
故障排除的第一步通常是验证 Nginx 服务本身的状态。根据您的操作系统,您通常会与 systemd 或 service(SysVinit)交互。
1. 检查 Nginx 服务状态
了解 Nginx 是运行中、已停止还是失败至关重要。status 命令提供了这一概览。
使用 systemd(常见于现代 Linux 发行版,如 Ubuntu 16.04+、CentOS 7+):
sudo systemctl status nginx
预期输出(活动/运行中):
● nginx.service - 高性能 Web 服务器和反向代理服务器
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-10-24 10:00:00 UTC; 1h ago
Docs: man:nginx(8)
Main PID: 1234 (nginx)
Tasks: 2 (limit: 4915)
CGroup: /system.slice/nginx.service
├─1234 nginx: master process /usr/sbin/nginx -g daemon on;
└─1235 nginx: worker process
如果输出显示 Active: inactive (dead) 或 Active: failed,则表明 Nginx 当前未提供流量服务。但这并不能说明原因。下一个线索通常是配置测试或系统日志。
sudo journalctl -u nginx -n 80 --no-pager
这将显示最近的服务日志,包括 systemd 的启动失败信息。查找有关未知指令、缺少证书文件、绑定失败或权限错误的消息。
2. 启动、停止和重新加载 Nginx
一旦确定了状态,就需要进行管理。根据需要,使用以下命令:
| 操作 | 命令(使用 systemctl) |
|---|---|
| 停止 服务 | sudo systemctl stop nginx |
| 启动 服务 | sudo systemctl start nginx |
| 重启 服务 | sudo systemctl restart nginx(先停止再启动) |
| 重新加载 配置 | sudo systemctl reload nginx(应用新配置而不中断连接) |
最佳实践:优先使用
reload而非restart在进行配置更改(如更新虚拟主机或 SSL 证书)时,始终使用reload。这可以优雅地应用更改,同时现有连接继续不受干扰。仅当reload失败或需要完全重置工作进程时才使用restart。
在任何重新加载之前,运行:
sudo nginx -t && sudo systemctl reload nginx
这种单行模式可以防止最常见的错误:重新加载损坏的配置并导致正在运行的服务器宕机。如果 nginx -t 失败,则不会执行重新加载命令。
验证配置文件
Nginx 启动失败或出现意外行为的最常见原因是配置文件(nginx.conf 或 /etc/nginx/sites-available/ 中包含的文件)中存在语法错误。Nginx 提供了一个出色的内置测试工具。
3. 测试配置语法
-t 标志测试配置文件的语法错误,并检查配置文件路径是否有效。
sudo nginx -t
成功输出示例:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
错误输出示例:
如果存在错误,Nginx 将指向确切的文件和行号。例如,缺少分号:
nginx: [emerg] unknown directive "server_name example.com" in /etc/nginx/sites-enabled/default:15
nginx: configuration file /etc/nginx/nginx.conf test failed
这种即时反馈允许您直接跳转到指定文件的第 15 行以更正拼写错误。
有时报告的行只是 Nginx 最终注意到问题的地方。缺少的 } 或 ; 可能在前几行。如果错误指向一个看起来正常的指令,请检查其上方块。
4. 显示活动配置
要确切查看 Nginx 当前正在运行的内容(特别是在多次配置合并或复杂的包含之后),请使用 -T 标志(大写 T):
sudo nginx -T
这将输出整个活动配置,可以将其通过管道传输到文件以进行比较或详细审查:
sudo nginx -T > current_nginx_config.txt
共享 nginx -T 输出时要小心。它可能包含内部主机名、证书路径、代理标头,有时还包含作为标头传递的机密信息。对于事件处理工作,它非常有用。对于工单或聊天,请先进行脱敏处理。
检查端口和监听器
如果 Nginx 无法启动并且日志提到 bind() to 0.0.0.0:80 failed,则可能是另一个进程已在监听该端口。
sudo ss -ltnp | grep -E ':80|:443'
典型输出显示本地地址、端口和进程名称。如果 Apache、Caddy、容器代理或旧的 Nginx 进程占用了该端口,Nginx 将无法绑定到它。
您还可以从服务器本身确认公共行为:
curl -I http://127.0.0.1
curl -Ik https://127.0.0.1
-I 仅获取标头。-k 忽略证书验证,这在针对为域名颁发的证书测试 localhost 时非常有用。从另一台机器,也测试真实主机名:
curl -I https://example.com
如果 localhost 工作正常但公共主机名失败,请检查防火墙规则、云安全组、DNS、负载均衡器或 CDN 配置。
DNS 值得单独检查,因为它可能使健康的 Nginx 服务器从外部看起来出现故障:
dig +short example.com
dig +short www.example.com
确保返回的地址是您期望的服务器或负载均衡器。如果您最近迁移了站点,过时的 DNS 可能会将一些用户发送到旧主机,而您自己的测试则访问新主机。
监控和日志分析
如果 Nginx 成功启动但提供错误的页面或返回 5xx 错误,则日志成为主要的事实来源。
5. 定位关键日志文件
默认情况下,Nginx 日志通常位于 /var/log/nginx/。两个基本文件是:
access.log:记录服务器处理的每个请求,包括 IP、请求时间、状态码和请求的资源。error.log:记录操作或请求处理期间遇到的警告、通知和严重错误。
6. 使用 tail 实时监控日志
要实时监控错误,请使用 tail 命令并带上跟随(-f)选项查看错误日志。
sudo tail -f /var/log/nginx/error.log
这在测试新部署的应用程序端点时非常宝贵,因为您可以立即看到 Nginx 或上游应用程序是否抛出错误。
对于繁忙的服务器,仅跟踪新的错误行并保持时间戳可见:
sudo tail -n 50 -f /var/log/nginx/error.log
然后在另一个终端中重现失败的请求:
curl -I https://example.com/failing/path
这种简单的双终端工作流程通常比在浏览器中点击更快,因为每个请求和日志条目都可以直接匹配。
7. 分析访问日志状态码
对于高流量问题,快速扫描访问日志中的状态码可以揭示问题:
- 4xx 代码(客户端错误):通常表示链接断开、文件缺失(404)或权限问题。
- 5xx 代码(服务器错误):表示 Nginx 本身未能完成请求,通常是由于上游连接超时(502/504)或内部服务器处理失败(500)。
使用 grep 过滤特定代码。例如,查找所有 502 Bad Gateway 错误:
sudo grep ' 502 ' /var/log/nginx/access.log | tail -n 20
快速的状态码计数可以显示您是在处理一个错误的 URL 还是更广泛的事件:
sudo awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head
常见模式:
404激增通常意味着部署路径错误、静态文件丢失或路由更改。403通常指向文件权限、目录权限或故意的访问规则。502通常意味着 Nginx 无法从上游服务获得有效响应。504通常意味着上游服务接受了连接但未及时响应。
对于上游故障,也要检查应用程序服务:
sudo systemctl status myapp
sudo journalctl -u myapp -n 100 --no-pager
将 myapp 替换为实际的服务名称。Nginx 只能代理存活且可达的内容。
高级诊断:详细信息和进程 ID
8. 强制调试日志记录(谨慎使用)
在非常棘手的情况下,提高日志记录级别可以揭示有关请求处理的更详细信息。这可以通过将配置中的 error_log 指令修改为 debug 来实现。
警告: 调试日志记录会非常快速地生成大量数据,应仅临时用于主动故障排除,因为它会严重影响性能。
更改指令后,必须使用 reload 或 restart Nginx 才能使更改生效。
9. 查找 Nginx 主进程 ID (PID)
进程 ID (PID) 用于向正在运行的主进程发送特定信号(例如,在 systemctl 之外进行优雅关闭或优雅重新加载)。PID 通常存储在一个文件中,通常是 /var/run/nginx.pid。
cat /var/run/nginx.pid
# 示例输出:1234
然后,如果需要,可以使用 kill 命令(例如,sudo kill -HUP 1234 使用 PID 强制重新加载):
大多数操作员应优先使用 systemctl reload nginx,因为它通过服务管理器进行,并且更容易审计。在最小系统、容器或 systemd 未管理进程的旧主机上,信号仍然有用。
按症状的常见命令行修复
如果配置编辑后 Nginx 失败:
sudo nginx -t
sudo journalctl -u nginx -n 80 --no-pager
修复报告的文件和行,然后在重新加载之前再次测试。
如果证书续订后 HTTPS 失败:
sudo nginx -t
sudo ls -l /etc/letsencrypt/live/example.com/
sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates -subject
这确认了证书文件存在,并显示了主题和有效期。
如果静态文件返回 403:
namei -l /var/www/example.com/index.html
namei -l 打印路径中每个目录的权限。Nginx 需要对父目录具有执行权限,对文件具有读取权限。
如果反向代理返回 502:
sudo grep 'connect() failed' /var/log/nginx/error.log | tail
sudo ss -ltnp | grep 3000
curl -I http://127.0.0.1:3000
这会检查上游是否正在监听以及是否在本地响应。
如果上游是 Unix 套接字而不是 TCP 端口,请检查套接字路径和权限:
sudo ls -l /run/myapp/myapp.sock
sudo grep -R "proxy_pass" /etc/nginx/sites-enabled /etc/nginx/conf.d
Nginx 工作进程用户需要访问套接字的权限。在许多系统上,该用户是 www-data 或 nginx,但在更改所有权或组之前,请在 nginx.conf 中确认。
对于间歇性故障,比较访问日志中成功和失败的请求。少量样本通常就足够了:
sudo grep ' 504 ' /var/log/nginx/access.log | tail -n 20
sudo grep ' 200 ' /var/log/nginx/access.log | tail -n 20
查找路径、上游响应时间字段(如果日志格式包含)或触发大量请求的特定客户端 IP 的模式。
故障排除工作流程
面对 Nginx 问题时,请按以下顺序操作:
- 检查状态:
sudo systemctl status nginx。 - 测试配置:如果启动失败,运行
sudo nginx -t。修复报告的错误。 - 重启/重新加载:如果修改了配置,使用
sudo systemctl reload nginx。 - 监控日志:如果运行但出现故障,在重现问题时使用
sudo tail -f /var/log/nginx/error.log。 - 分析访问日志:查看
access.log中的状态码,以确定故障的性质(4xx 与 5xx)。
这个顺序可以避免您猜测。状态告诉您 Nginx 是否在运行,配置测试告诉您它是否可以加载,日志告诉您实际请求期间发生了什么,而本地 curl 检查则将 Nginx 问题与上游或网络问题分开。
工作时保留简短的事件记录:执行的命令、看到的结果以及所做的更改。这可以避免重复检查,并使交接更加容易。