Nginx 故障排除:解决 Web 服务器问题的常用命令行方案

使用实用的 Nginx 命令行检查服务状态、配置错误、日志、端口以及常见的 4xx 或 5xx 故障。

Nginx 故障排除:解决 Web 服务器问题的常用命令行方案

当 Nginx 出现故障时,最初的几分钟通常用于缩小问题范围。是服务停止了?配置更改失败?其他进程已在使用端口 80?Nginx 正常运行但上游应用宕机?如果按正确顺序执行检查,命令行可以快速给出答案。

我倾向于从破坏性最小的命令开始:检查状态、测试配置、读取日志,然后才重新加载或重启。重启可能会隐藏有用的证据,因此只有在了解问题所在后才将其作为修复手段。

基本 Nginx 管理命令

故障排除的第一步通常是验证 Nginx 服务本身的状态。根据您的操作系统,您通常会与 systemdservice(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 来实现。

警告: 调试日志记录会非常快速地生成大量数据,应临时用于主动故障排除,因为它会严重影响性能。

更改指令后,必须使用 reloadrestart 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-datanginx,但在更改所有权或组之前,请在 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 问题时,请按以下顺序操作:

  1. 检查状态sudo systemctl status nginx
  2. 测试配置:如果启动失败,运行 sudo nginx -t。修复报告的错误。
  3. 重启/重新加载:如果修改了配置,使用 sudo systemctl reload nginx
  4. 监控日志:如果运行但出现故障,在重现问题时使用 sudo tail -f /var/log/nginx/error.log
  5. 分析访问日志:查看 access.log 中的状态码,以确定故障的性质(4xx 与 5xx)。

这个顺序可以避免您猜测。状态告诉您 Nginx 是否在运行,配置测试告诉您它是否可以加载,日志告诉您实际请求期间发生了什么,而本地 curl 检查则将 Nginx 问题与上游或网络问题分开。

工作时保留简短的事件记录:执行的命令、看到的结果以及所做的更改。这可以避免重复检查,并使交接更加容易。