核心是“轮转+压缩+清理”协同配合源头日志减量:用logrotate安全轮转(sharedscripts+postrotate发usr1)、dateext/compress/delaycompress/rotate30/notifempty;nginx端调优error_log级别、access_log off静态资源、精简log_format、启用buffer;find定期清理90天前.gz文件;磁盘满时用lsof查deleted句柄,echo清空再reopen释放空间。

核心是“轮转 + 压缩 + 清理”自动协同,再配合源头日志减量,才能真正防住磁盘被撑爆。
用 logrotate 实现安全轮转与压缩
这是最稳妥、系统级支持的方案,不依赖 Nginx 重启,也不会丢日志:
- 配置 sharedscripts 和 postrotate 段,确保所有日志文件处理完后,统一发 USR1 信号(
nginx -s reopen),让 worker 进程切换到新文件,避免写入中断 - 启用 dateext(文件名带日期)、compress(自动 gzip 压缩)、delaycompress(上一轮才压缩,防止正在写的文件被误压)
- 设 rotate 30 保留最近 30 份,避免无限堆积;notifempty 防止空日志也被轮转
从 Nginx 配置端减少日志写入量
轮转解决“怎么存”,优化解决“存什么”,能直接降低 30%~60% 日志体积:
- 错误日志只记录 warn 及以上:
error_log /var/log/nginx/error.log warn; - 对静态资源(js/css/img)、健康检查接口(如
/healthz)加access_log off; - 精简
log_format:去掉非必要字段,比如$http_user_agent或$http_x_forwarded_for - 启用缓冲写入:
access_log /var/log/nginx/access.log main buffer=64k flush=5s;
定期清理过期压缩日志
logrotate 不负责永久保存,需额外清理老旧归档:
- 用
find定期删掉 90 天前的.log.gz文件,例如:find /var/log/nginx/ -name "*.log.gz" -mtime +90 -delete - 建议把这条命令写进
/etc/cron.weekly/cleanup-nginx-logs,避免手动遗漏 - 切忌直接
rm *.log或> access.log—— 若句柄未释放,磁盘空间仍不释放,还可能引发写入错乱
磁盘已满时的应急处理
别删文件、别重启,先快速释放空间:
- 查哪个分区满了:
df -h | grep '/var',重点关注/var/log和/var/lib/nginx - 看是否有“已删但句柄卡住”的日志:
lsof +L1 | grep nginx,若有deleted字样,说明文件被删但进程还在写 - 安全清空当前日志内容:
echo "" > /var/log/nginx/access.log(不删文件,只清内容) - 再执行
nginx -s reopen,让 Nginx 重开文件句柄,磁盘空间立刻释放











