高并发下nginx访问日志“丢记录”的根本原因在于写入链路三环节异常:权限与文件句柄问题(如用户不匹配、轮转导致inode变更、selinux拦截)、磁盘inodes或空间耗尽(df -i满时仍报“no space left on device”)、以及文件句柄数超限或日志缓冲机制(buffer/flush)导致延迟或丢弃。

访问日志在高并发下“丢记录”,通常不是真的没记,而是写入失败、被覆盖、或根本没走到写入环节。核心要从日志写入链路的三个关键环节入手:Nginx进程能否打开/写入日志文件、系统内核能否完成IO、磁盘空间与句柄是否充足。
检查日志文件写入权限与归属
Nginx worker 进程必须对 access.log 文件有可写权限,且父目录也要有执行(x)权限(否则无法进入目录)。常见问题包括:
- 日志文件被 root 创建,但 worker 以 nobody 或 nginx 用户运行,导致无权追加内容
- 日志轮转脚本用 cp + truncate 替换原文件,实际是新建 inode,Nginx 仍往旧文件句柄写——新文件空着,旧文件不更新(表现为“日志停更”)
- SELinux 或 AppArmor 启用时拦截了写操作(可通过 ausearch -m avc -ts recent 查看拒绝日志)
确认磁盘空间与 inodes 是否耗尽
空间满是高频原因,但容易被忽略的是 inodes 耗尽——即使 df -h 显示空间充足,df -i 可能显示 100%。尤其当大量小日志文件未清理(如按小时切分却未删除),或日志轮转策略不当(如用 gzip 压缩但未删源文件)时极易触发。
典型报错:open() "/var/log/nginx/access.log" failed (28: No space left on device) ——注意这里 “No space left on device” 指的是 inodes 不足,不单是磁盘块。
排查文件句柄(FD)是否被占满
每个打开的日志文件、每个客户端连接、每个 upstream socket 都占用一个文件句柄。高并发场景下,若系统级或 Nginx 级句柄限制过低,Nginx 可能无法打开 access.log,直接跳过写入。
- 查当前 Nginx 打开的句柄数:ls -l /proc/$(cat /var/run/nginx.pid)/fd/ | wc -l
- 查系统限制:cat /proc/sys/fs/file-max 和 ulimit -n(需在 nginx 启动用户下执行)
- 若接近上限,需调大:worker_rlimit_nofile 指令设为 65535,并同步调整系统 /etc/security/limits.conf
验证日志缓冲与异步写入行为
Nginx 默认启用 buffered logging(通过 access_log ... buffer=64k flush=5s 控制),即先缓存再刷盘。这意味着:
- 突发流量下,buffer 满后可能丢弃新日志(而非阻塞请求)
- 服务异常终止(如 kill -9)时,未 flush 的日志永久丢失
- flush 时间间隔内,实时 tail -f 看不到最新条目
如需强一致性,可关闭缓冲:access_log /path/to/access.log main buffer=0;,但会轻微增加 IO 压力。











