优先查error.log中错误码:(13: Permission denied)指向权限或SELinux拦截,(24: Too many open files)表明文件描述符耗尽;再用sudo -u nginx验证访问、sestatus/ausearch确认SELinux、prlimit检查fd限制。

遇到 Nginx 报错时,日志里出现 Permission denied,但实际不是文件权限问题——很可能是文件描述符(file descriptor)耗尽或 SELinux 拦截导致的“假权限错误”。这两类问题在错误日志中表现高度相似(比如都显示 (13: Permission denied)),容易误判、反复折腾。关键不在“看报错文字”,而在“看上下文和系统状态”。
区分 file descriptor 耗尽和真实权限拒绝
文件描述符不足时,Nginx 可能无法打开日志、临时文件、上游连接甚至静态资源,错误日志常含以下特征:
-
open() "/var/log/nginx/access.log" failed (24: Too many open files)—— 明确提示 24,不是 13 connect() failed (24: Too many open files) while connecting to upstream- 错误日志中大量重复失败,且 同一路径反复报错,但用
sudo -u nginx cat 文件却能成功读取
验证方法:
- 查当前限制:
cat /proc/$(pgrep nginx)/limits | grep "Max open files" - 查已用数量:
ls -1 /proc/$(pgrep nginx)/fd/ | wc -l - 临时调高(测试用):
sudo prlimit -n 65536 $(pgrep nginx)
识别 SELinux 拦截而非配置或权限错误
SELinux 拒绝访问时,传统权限完全正确,ls -l 和 sudo -u nginx cat 都成功,但 Nginx 仍返回 403 或日志报 (13: Permission denied)。这是最典型的混淆点。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 先确认状态:
sestatus→ 若为enforcing,需继续排查 - 查拦截记录:
ausearch -m avc -ts recent | grep nginx - 典型输出含:
avc: denied { read } for ... comm="nginx" name="index.html" dev="sda1" ino=123456 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
若查到此类记录,说明是 SELinux 上下文不匹配,不是 chmod 或 chown 的问题。
快速交叉验证三步法
当不确定是 fd 耗尽、普通权限还是 SELinux 导致时,按顺序执行:
-
第一步:检查错误码——日志中是
(13: Permission denied)还是(24: Too many open files)?前者跳过 fd 排查 -
第二步:切换用户验证——
sudo -u nginx ls -l /your/site/root和sudo -u nginx cat /your/site/root/index.html。若全部成功,基本排除传统权限问题 -
第三步:临时禁用 SELinux 测试——
sudo setenforce 0,刷新页面。若 403 消失,立即还原并修复上下文:sudo semanage fcontext -a -t httpd_sys_content_t "/path/to/site(/.*)?",再sudo restorecon -Rv /path/to/site
避免日志混淆的根本建议
生产环境不要依赖“禁用 SELinux”或“chmod 777”来绕过问题。真正可靠的排查逻辑是:
- 始终优先查看
/var/log/nginx/error.log的完整上下文,不止第一行 - 把
ausearch和prlimit当成和ls -l一样常用的命令 - 部署前统一设置:调整 systemd 的
LimitNOFILE,预设 SELinux 上下文,避免上线后才发现日志被“伪装”

















