Skip to content

nginx 日志轮转未重载排查与修复记录 ​

记录日期: 2026-10-19
影响范围: 正式服务器 47.121.197.139 的系统 nginx 访问/错误日志轮转; 不涉及应用服务、数据库、正式流量与蓝绿实例。时间为北京时间(CST)。

1. 事件概述 ​

在排查正式环境用户使用情况时发现:/var/log/nginx/access.log 为 0 字节 (创建于 10/13 00:00),而实际流量持续写入 access.log.1(10/12 15:43 起, 已 4.5MB)。说明日志轮转后 nginx 没有重新打开日志文件,此后每天的轮转被 notifempty 跳过,新的日志将一直堆积在 .1 文件中,不再滚动。

同机还存在第二个独立缺陷:logrotate 每天以 exit 1 结束(重复条目报错), 掩盖了上述 postrotate 失败。

两个问题均已在正式服务器修复并完成端到端验证;开发服务器不受影响。

2. 现象与初步排查 ​

  • access.log 0 字节(10/13 创建),error.log 0 字节(10/13 创建)。
  • access.log.1 4.5MB 且 mtime 持续更新;error.log.1 同理。
  • nginx master(当时 PID 623777)的打开句柄指向 .1 文件: /proc/623777/fd/4 -> /var/log/nginx/access.log.1。
  • /var/lib/logrotate/status 中 nginx 两个日志的最近轮转日期停留在 2026-10-13,与"轮转后未重开、随后被 notifempty 跳过"一致。

3. 排查证据 ​

  1. 轮转配置依赖已丢失的 init 脚本:

    bash
    grep -A2 postrotate /etc/logrotate.d/nginx
    # postrotate
    #     invoke-rc.d nginx rotate >/dev/null 2>&1
    
    dpkg --verify nginx nginx-common
    # missing   c /etc/init.d/nginx      ← 包文件缺失
    
    invoke-rc.d nginx rotate; echo rc=$?
    # /usr/sbin/invoke-rc.d: ... No such file or directory
    # rc=127
  2. syslog 保留窗口内(2026-09-23 起)每天 00:00 出现:

    logrotate[...]: error: error running shared postrotate script for '/var/log/nginx/*.log '
  3. 包升级记录与故障时间吻合:

    2026-09-15 06:28  upgrade nginx:amd64 1.24.0-2ubuntu7.17 → 7.18   (unattended-upgrades)
  4. 重复条目(独立缺陷):

    logrotate[...]: error: xiedao-dev-dns-watch:1 duplicate log entry for /var/log/nginx/xiedao-dev-dns-watch.log
    logrotate[...]: error: found error in file xiedao-dev-dns-watch, skipping
    systemd: logrotate.service: Failed with result 'exit-code'

    来源:/etc/logrotate.d/xiedao-dev-dns-watch(2026-09-09 DNS 切换时按仓库 Deploy/docker-dev/config/cutover-logrotate.conf 安装)与该机 /etc/logrotate.d/nginx 的 /var/log/nginx/*.log 通配重复声明同一文件。

4. 根因判断 ​

主因(日志未重载): /etc/logrotate.d/nginx 的 postrotate 调用 invoke-rc.d nginx rotate,它依赖 /etc/init.d/nginx;该脚本已不存在 (dpkg --verify 标记 missing),postrotate 从未成功执行。nginx 收不到 USR1,继续写已改名的旧 inode;create 出来的新 access.log 一直为 0 字节,notifempty 使之后每天的轮转直接跳过。

次要(logrotate.service 每天失败): 重复条目使 logrotate 整体以 exit 1 结束。nginx 条目按文件名顺序(nginx 在 xiedao-dev-dns-watch 之前)仍会被 处理,但整次运行被标记失败,真实错误被掩盖。

易混淆点: systemctl reload nginx 是 HUP(重载配置),不会重开日志; 日志重开必须向 master 发送 USR1(或 nginx -s reopen)。

5. 已执行的正式服务器修复 ​

备份(改动前原文件):

/root/backup-logrotate-20261019-093644/
├── nginx.conf.orig                 (329B, 2023-12-01)
└── xiedao-dev-dns-watch.orig       (219B, 2026-09-09)
  1. 修改 /etc/logrotate.d/nginx 的 postrotate:

    diff
     	postrotate
    -		invoke-rc.d nginx rotate >/dev/null 2>&1
    +		if [ -s /run/nginx.pid ]; then kill -USR1 "$(cat /run/nginx.pid)"; fi
     	endscript
  2. 删除 /etc/logrotate.d/xiedao-dev-dns-watch。该日志此后由 nginx 通配条目 继续轮转(保留策略由 3 天变为 14 天);该文件自 2026-09-15 起无写入, 属已完成的切换任务遗留。

  3. 立即向 nginx master 发送 USR1 完成重开(不重启、无中断、不丢日志), 随后执行一次真实轮转做端到端验证。

6. 验证结果 ​

  • nginx 打开句柄指向 access.log / error.log,不再指向 .1 文件; 实测请求(GET / 200)写入新 access.log。
  • 真实轮转输出包含 renaming ... access.log to access.log.1、 creating new access.log、running postrotate script(无报错), rotate 14 的链式滚动与超期删除正常。
  • 堆积的 4.5MB 日志压缩为 access.log.2.gz(281KB),无数据丢失。
  • /var/lib/logrotate/status 更新为 2026-10-19。
  • 全局 logrotate -d /etc/logrotate.conf 无 error、无 duplicate。
  • logrotate.timer 下次运行:2026-10-20 00:00。

7. 影响范围确认 ​

  • 开发服务器 8.134.105.163:宝塔 nginx + 自带 /etc/logrotate.d/xiedao-dev-nginx(使用 nginx -s reopen), /etc/init.d/nginx 存在,logrotate 无失败记录,不受影响。
  • 同机 MySQL(每日)、Redis(每周)日志轮转正常。
  • 事件期间应用可用性未受影响;日志中 502 均来自扫描器访问不存在的路径, 与本次问题无关。

8. 防复发与后续 ​

  1. 仓库 Deploy/docker-dev/config/cutover-logrotate.conf 已加注释:目标主机 若已有 /var/log/nginx/*.log 通配配置,不要安装该重复条目。

  2. /etc/logrotate.d/nginx 是 dpkg conffile:当前系统 apt 未设置 Dpkg::Options,dpkg 默认保留本地版本,后续 nginx 包升级一般不会覆盖。 若升级后复发,按第 3 节证据(dpkg --verify + syslog 关键字)定位, 并恢复第 5 节的 postrotate。

  3. 次日复核(应显示 status=0/SUCCESS):

    bash
    ssh -i ~/.ssh/XieDao.pem root@47.121.197.139 \
      'systemctl status logrotate.service --no-pager | head -5'
  4. 遗留清理(可选,需另行确认):本机仍保留切换期产物 /etc/nginx/conf.d/xiedao-dev-dns-watch.conf、xiedao-dev-im-forward.log 等;切换任务 status=complete 且 timer 已禁用,相关日志自 9/15 起为空。 确认无引用后可清理 vhost 与日志文件,缩小轮转面。

携岛 XieDao · 内部文档