核心是用 usr1 信号重开日志而非 reload,确保毫秒级原子切换文件句柄、不中断请求、不丢日志;配合 logrotate 的 delaycompress、dateext 及 postrotate 中 kill -usr1 正确调用,实现安全归档。

保障业务连续性的同时完成 Nginx 日志安全归档,核心是“不中断写入 + 不丢失记录 + 不干扰请求”。关键不在轮转动作本身,而在信号通知方式、文件句柄处理和归档时机的协同设计。
用 USR1 信号重开日志,而非 reload 或 kill
Nginx 收到 USR1 信号后,会原子性地关闭旧日志文件句柄、打开新文件并继续写入,整个过程毫秒级完成,对正在处理的请求完全透明。这比 nginx -s reload 或 systemctl reload nginx 更轻量——后者会触发 worker 进程平滑重启,存在极小概率丢连接或延迟响应。
- 确保 logrotate 配置中
postrotate段调用的是kill -USR1 $(cat /var/run/nginx.pid),不是 reload 命令 - 若 PID 文件路径非标准(如在
/usr/local/nginx/logs/nginx.pid),需同步更新脚本中的路径 - 避免直接
mv或cp日志文件——Nginx 仍向原 inode 写入,磁盘空间不会释放,还可能因权限错乱导致后续写入失败
启用 delaycompress + compress 组合压缩旧日志
压缩操作本身不危险,但若在日志正被写入时强行 gzip,会导致内容截断或损坏。使用 delaycompress 可规避该风险:它确保最新一轮轮转后的日志文件暂不压缩,等下一轮轮转时才对上一轮文件执行压缩。这样既节省空间,又杜绝了“边写边压”的竞态问题。
- 搭配
compress启用 gzip 压缩,通常可减少 70%~90% 体积 - 加
dateext和dateyesterday,让归档文件名明确对应实际日期(如access.log-20260903),避免语义混淆 - 不要设
maxage替代rotate——前者按文件修改时间判断,而轮转后文件时间戳会变,易误删
分离日志路径与归档逻辑,避免单点故障
把日志写入路径、轮转配置、归档目标三者解耦,能提升容错能力。例如:
- 让 Nginx 始终往
/var/log/nginx/access.log写入(固定路径),logrotate 负责按规则切走、重命名、压缩 - 不把日志直接写进
/data/archive/等挂载目录——若该目录临时不可写,Nginx 会报错并可能停止记录 - 若用
rotatelogs,确保其二进制路径(如/usr/bin/rotatelogs)对 nginx worker 用户(如www-data)可执行,且日志目录有写权限
上线前必须验证的三件事
配置写完不能只等 cron 触发,必须手动验证是否真正生效:
- 运行
logrotate -f /etc/logrotate.d/nginx强制触发一次,观察/var/log/nginx/是否生成access.log.1.gz,原access.log是否清空且仍有新请求写入 - 用
lsof -p $(cat /var/run/nginx.pid) | grep log查看 nginx 进程当前打开的日志文件句柄,确认已指向新文件 - 检查
error.log末尾是否有reopening logs提示(开启debug级别可看到更详细信息)











