一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Nginx 如何在 Nginx 中使用 logrotate 的 `copytruncate` 模式在不重启服务下切割日志

时间:2026-08-08 08:59:54 编辑:袖梨 来源:一聚教程网

copytruncate 是 logrotate 的一种日志切割方式,先拷贝再清空原文件以保持 inode 不变,使 Nginx 无需重启或 reload 即可继续写入;但存在少量日志丢失风险,且不兼容 dateext 和 create。

Nginx 本身不支持直接重开日志文件(即不发 kill -USR1 也能刷新日志),所以用 logrotate 配合 copytruncate 是一种“免重启”切割方案,但要注意它本质是妥协式做法,有日志丢失风险,仅适用于无法优雅 reload 的场景。

copytruncate 是什么,为什么能不重启

copytruncate 的逻辑分两步:

  1. 先把当前正在写入的 access.log 拷贝一份(比如 access.log-20260729
  2. 再清空原文件(> /var/log/nginx/access.log),保留 inode 不变,Nginx worker 进程仍往同一文件句柄写入

因为进程没感知文件被清空,也不需要重新打开日志文件,所以无需 nginx -s reloadkill -USR1

⚠️ 注意:Nginx worker 可能缓存少量日志(几 KB)或延迟 flush,清空瞬间可能丢失最后几行日志。生产环境更推荐用 create + postrotate reload 组合。

正确配置 copytruncate 的关键点

  1. 必须指定 copytruncate,否则 logrotate 默认会 rename 原文件并新建——但 Nginx 不会自动切到新文件,导致日志继续写进旧 inode(即 rename 后的 .1 文件),原 access.log 变为空白
  2. 不能同时用 createcreate 是为 rename 后新建空文件准备的;而 copytruncate 下原文件还在,新建操作多余且可能权限错乱
  3. 避免和 dateext 冲突dateext 依赖 rename 行为,与 copytruncate 不兼容,会导致日期后缀不生效
  4. 建议加 missingok:防止日志文件暂不存在时报错中断

示例配置 /etc/logrotate.d/nginx

/var/log/nginx/*.log {dailyrotate 30compressdelaycompressmissingokcopytruncatedateformat -%Y%m%d}

⚠️ dateformatcopytruncate 下实际无效(因无 rename),若需日期标识,得靠 dateext + postrotate 脚本配合,但这已脱离 copytruncate 本意。

手动验证和触发

调试时先用 -d 检查语法:

logrotate -d /etc/logrotate.d/nginx

强制执行一次(不等 cron):

logrotate -f /etc/logrotate.d/nginx

执行后观察:

  1. access.log 大小归零(但 inode 不变)
  2. 出现 access.log-20260729(如果用了 dateext 且没冲突)或 access.log.1(默认命名)
  3. nginx 访问仍在写入 access.log,无中断

更稳妥的替代方案(推荐)

如果允许轻微中断(毫秒级),优先用标准 reload 方式:

/var/log/nginx/*.log {dailyrotate 30compresscreate 0644 www-data www-datasharedscriptspostrotateif [ -f /var/run/nginx.pid ]; thenkill -USR1 `cat /var/run/nginx.pid`fiendscript}

这种方式无日志丢失,权限可控,且 create 确保新日志文件属主正确。

不复杂但容易忽略细节

热门栏目