Nginx启动后会持续向access.log和error.log写入访问记录和错误信息,如果服务器没有部署任何日志管理策略,这两个文件会随着时间不断增大,最终可能占满磁盘分区。手动执行mv命令虽然能临时释放空间,但会导致Nginx仍然持有旧文件的文件描述符,后续日志依然写入被重命名的文件,新日志文件并不会自动创建。真正可靠的方案是引入logrotate,让它在固定的时间点完成日志切换、归档和压缩,并通过信号通知Nginx重新打开日志文件。

logrotate的轮转动作并不是简单地把日志文件改名,而是在重命名或移除旧日志后,创建一个新的空日志文件,再触发Nginx执行reopen操作。Nginx在收到USR1信号后会重新打开配置中指定的所有日志文件,这样后续写入就会指向新创建的文件,整个过程不会造成服务中断,对在线业务几乎没有影响。
logrotate与Nginx的协作原理
要理解logrotate如何管理Nginx日志,首先需要明确一个关键点:Linux进程打开文件时使用的是文件描述符,而不是文件路径。Nginx启动时打开/var/log/nginx/access.log,即使后来有人把这个文件重命名为access.log.1,Nginx依然会继续向原来的描述符写入数据,也就是写进access.log.1里。这正是手动移动日志文件后Nginx不生成新日志的根本原因。
logrotate通过两步动作解决这个问题。第一步,它根据配置把当前日志文件改名,例如改成access.log.1,然后创建新的access.log,并设置合适的属主和权限。第二步,它执行postrotate脚本,向Nginx的主进程发送USR1信号。Nginx收到信号后,会关闭所有已打开的日志文件,再依据配置文件重新打开它们。由于此时新的access.log已经存在,Nginx的后续日志就会写入新文件,旧文件则安全地进入归档或压缩流程。
这种设计的优势在于无需重启Nginx,也不要求Nginx支持日志模块热加载。只要Nginx是以主进程加工作进程的方式运行,并且主进程PID文件路径正确,logrotate脚本就能稳定工作。对于使用容器或自定义编译的Nginx,同样适用,只需确保postrotate脚本中的PID文件路径与实际环境一致。
基础配置:编写一个Nginx日志轮转文件
logrotate的主配置文件通常是/etc/logrotate.conf,而各个服务的独立配置可以放在/etc/logrotate.d/目录下。为Nginx创建配置文件/etc/logrotate.d/nginx,logrotate程序每天运行时会自动读取该目录中的配置。下面是一个最基础的Nginx日志轮转配置示例。
/var/log/nginx/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
create 0640 nginx adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 $(cat /var/run/nginx.pid)
fi
endscript
}
这段配置的第一行/var/log/nginx/*.log表示对Nginx日志目录下所有以.log结尾的文件执行轮转。大括号内是指令集合,daily指定每天执行一次轮转,rotate 14表示保留14份历史日志,超过数量的最旧文件会被删除。missingok允许日志文件不存在时不报错,notifempty则跳过空文件,避免无意义的轮转。
compress启用gzip压缩,配合delaycompress可以让最近一次轮转的日志先不压缩,等到下一次轮转时再压缩,这样能保证最新的归档文件便于查看。create 0640 nginx adm指定新日志文件的权限、属主和属组,Nginx进程需要对该文件有写权限。sharedscripts告诉logrotate在多个日志文件轮转完成后只执行一次postrotate脚本,而不是每个文件都执行一次。postrotate和endscript之间的内容就是轮转完成后要执行的shell命令。
进阶配置:按大小分割、日期命名与归档目录
除了按天轮转,logrotate还支持按文件大小触发轮转。如果需要更精细地控制日志增长速率,可以把daily替换为size 100M,表示当日志文件达到100MB时立即轮转,而不必等到每天定时任务。这种方式适合流量波动较大的站点,能有效防止单日日志过大。同时,如果希望保留的归档文件名中包含具体日期,可以添加dateext和dateformat参数。
/var/log/nginx/*.log {
size 100M
rotate 30
missingok
notifempty
compress
delaycompress
dateext
dateformat -%Y%m%d
create 0640 nginx adm
sharedscripts
postrotate
nginx -s reopen 2>/dev/null || true
endscript
}
上面的配置中,size 100M是触发条件,rotate 30保留30份归档,dateext让归档文件名自动追加日期后缀,例如access.log-20250615.gz。dateformat -%Y%m%d定义日期格式,其中%Y代表四位年份,%m代表月份,%d代表日期。注意日期后缀前的短横线是普通字符,会被保留。脚本部分使用了nginx -s reopen命令代替直接发送信号,这要求nginx命令在PATH中可用,并且该命令能正确读取Nginx配置。
如果担心归档日志混入当前日志目录造成混乱,可以使用olddir指令把归档文件移动到指定目录。例如添加olddir /var/log/nginx/old后,轮转产生的access.log.1等文件会被移动到/var/log/nginx/old目录下。需要注意该目录必须预先创建并保证logrotate有写权限,否则轮转会失败。maxage指令可以设置归档文件的最大保留天数,超过该天数的旧日志即使数量未达到rotate限制也会被删除。
另一个值得关注的指令是su。某些Linux发行版在root运行logrotate时,如果日志文件属主不是root,可能会警告权限问题。可以在配置块中添加su nginx nginx,让logrotate以指定用户和组执行轮转,避免产生安全隐患。不过该指令仅在较新版本的logrotate中支持,使用前可以通过man logrotate确认版本兼容性。
调试logrotate与常见问题排查
部署配置文件后,建议先用调试模式验证语法和匹配路径是否正确。执行logrotate -d /etc/logrotate.d/nginx可以显示即将执行的轮转动作,但不会真正修改文件。-d参数会输出详细的处理过程,包括每个日志文件是否匹配、会执行哪些指令以及可能的错误。如果在调试输出中看到类似error: error running shared postrotate script,通常说明postrotate脚本中的命令执行失败,需要检查Nginx的PID文件路径是否正确,或者nginx命令是否可用。
强制立即执行一次轮转可用于测试完整流程,使用logrotate -f /etc/logrotate.d/nginx。在执行前建议先备份日志目录,并观察执行后新日志文件是否被创建、Nginx是否继续写入新文件。如果发现Nginx仍然写入旧文件,大概率是postrotate脚本没有成功向Nginx发送信号。可以通过手动执行脚本中的命令来定位问题,例如运行kill -USR1 $(cat /var/run/nginx.pid),然后查看access.log是否开始增长。
压缩失败也是常见现象。如果compress指令没有生效,检查是否安装了gzip,以及delaycompress导致最新归档未压缩是否被误判为故障。另外,当使用olddir时,如果旧目录不存在或权限不足,logrotate会跳过轮转并记录错误,可以使用ls -ld查看目录属主和权限,确保与配置中的create指令相匹配。SELinux或AppArmor策略也可能阻止logrotate访问某些目录,此时需要查看系统审计日志,调整策略或使用su指令切换运行用户。
对于多台服务器上一致的Nginx日志管理需求,可以将同一份logrotate配置通过配置管理工具分发,只需修改日志路径和PID文件路径即可。日常维护中还可以结合监控系统对日志目录使用率设置告警,当轮转策略失效导致磁盘占用异常时能及时发现,避免影响线上服务。
Nginx日志分割logrotate配置日志轮转修改时间:2026-08-23 13:19:54