Nginx日志按天切割实操:logrotate配置与不生效排查

    发布时间:2026-09-19 05:00 更新时间:2026-09-19 05:00 阅读量:0

    很多站长都有过这样的经历:某天收到磁盘告警,登上服务器执行 df -h 一看根分区快满了,再用 du 一层层找下去,最后发现元凶是 /www/wwwlogs 或者 /var/log/nginx 下面那个几 GB 的 access.log。访问日志本身是排障利器,但它默认只追加不轮转,只要站点有流量,这个文件就会一直变大,直到把磁盘写满、数据库和 PHP 会话写不进去、网站全面报错。

    解决办法并不复杂:让日志按天切割,旧日志压缩归档,只保留最近若干天。Linux 上这件事的标准工具是 logrotate,宝塔面板也内置了对应的计划任务。下面把配置写法和常见坑一次讲清,照着做完,日志目录基本不会再失控。

    logrotate 是怎么切日志的

    logrotate 的本质是一个定时执行的文件轮转器,通常由系统的 cron 或 systemd timer 每天触发一次。它的工作流程可以理解为:把当前的 access.log 改名成带日期的归档文件,然后通知 Nginx 重新打开一个新的 access.log 继续写,最后按配置压缩旧文件、删除超期文件。

    这里有个关键点容易被忽略:单纯改名是不够的。Linux 中正在被进程打开的文件,改名后进程手里的文件句柄仍然指向原来那个 inode,它会继续往改名后的文件里写。所以 logrotate 必须配合 postrotate 脚本,让 Nginx 重新打开日志文件,否则你会看到新日志文件是空的,旧文件还在不停变大。

    先确认系统里有没有 logrotate:

    which logrotate
    logrotate --version
    ls /etc/logrotate.d/
    

    如果命令不存在,CentOS 系可以 yum install logrotate,Debian/Ubuntu 系用 apt install logrotate,具体包名以官方源为准。接下来在 /etc/logrotate.d/ 下新建一个配置文件,例如 nginx:

    /www/wwwlogs/*.log {
        daily
        rotate 14
        missingok
        notifempty
        compress
        delaycompress
        dateext
        dateformat -%Y%m%d
        create 0640 www www
        sharedscripts
        postrotate
            if [ -f /www/server/nginx/logs/nginx.pid ]; then
                kill -USR1 $(cat /www/server/nginx/logs/nginx.pid)
            fi
        endscript
    }
    

    逐行解释一下常用参数。daily 表示每天轮转一次;rotate 14 表示保留 14 份归档,超出的自动删除,这个数字按你的磁盘容量和合规要求调整;missingok 让日志不存在时不报错;notifempty 表示文件为空就跳过,避免生成一堆空归档;compress 开启 gzip 压缩,delaycompress 表示延后一次再压缩,方便刚切割完还能直接看原始内容;dateext 和 dateformat 让归档文件名带上日期,比默认的数字后缀直观得多。

    create 0640 www www 指定新建日志文件的权限和属主,这里要和 Nginx 实际运行用户保持一致,宝塔环境下通常是 www,用 ps aux | grep nginx 可以确认。sharedscripts 配合 postrotate 里的 kill -USR1,作用是所有匹配到的日志文件只执行一次重开动作,USR1 信号是 Nginx 官方支持的重新打开日志方式。

    配置写完后不要直接等第二天,先手动验证一遍:

    logrotate -d /etc/logrotate.d/nginx
    logrotate -vf /etc/logrotate.d/nginx
    ls -lh /www/wwwlogs/
    

    -d 是 dry run,只打印将要执行的动作不实际改动,适合检查匹配路径和参数有没有写错;-vf 是强制执行并输出详细过程。执行完再看目录,应该能看到 access.log 和 access.log-20260915.gz 这类文件并存。

    宝塔面板的日志切割任务

    如果你用的是宝塔面板,其实不一定非要手写 logrotate 配置。面板的「计划任务」里有一个「日志切割」类型,本质也是调用 logrotate,只是把配置和触发入口包了一层图形界面。添加任务时选择日志切割,填好要切割的日志目录,保存后面板会生成对应的配置并挂到自己的定时调度里。

    用面板的好处是省心,坏处是出问题时不好定位,因为配置藏在面板的调度目录里。几个实践中的注意点:

    第一,面板的日志切割和系统自带的 /etc/logrotate.d/nginx 如果同时存在,可能出现同一天被切两次、归档文件命名打架的情况。建议二选一,用面板就检查一下系统目录里有没有重复配置。

    第二,宝塔的网站日志默认放在 /www/wwwlogs/ 下,按域名分文件,日志格式由面板的 Nginx 配置决定。切割配置里的路径要写通配符 *.log,如果只写了某个域名,其他站点照样会涨。

    第三,面板的「网站日志」开关如果关掉了,Nginx 配置里就没有 access_log 指令,这时候切割任务再正常也没有文件可切,排查时先确认日志确实在写。

    第四,宝塔的日志切割任务执行用户和权限,要和日志文件属主匹配。如果切割后新文件属主变成 root,Nginx 以 www 身份运行就写不进去,表现为切割完成后网站日志停止更新。

    切割不生效怎么排查

    日志切割失败通常有几种典型表现,按现象反查效率最高。

    表现一:归档文件根本没生成。先确认 logrotate 的定时任务在跑。CentOS 系可以看 /etc/cron.daily/logrotate 是否存在,或者 systemctl status logrotate.timer;Debian 系查看 /etc/cron.daily/ 和 systemd timer。再看配置文件的语法,用 logrotate -d 直接跑一遍,报错信息会明确告诉你哪一行有问题,常见的是路径写错、大括号不配对、postrotate 缺少 endscript。

    表现二:归档生成了,但新日志文件是空的或者旧文件还在涨。这是典型的「没重开日志句柄」。检查 postrotate 脚本里的 pid 路径对不对,宝塔环境下 Nginx 的 pid 文件一般在 /www/server/nginx/logs/nginx.pid,编译安装和 yum 安装的位置不一样。也可以手动测试信号是否有效:

    cat /www/server/nginx/logs/nginx.pid
    kill -USR1 $(cat /www/server/nginx/logs/nginx.pid)
    ls -l /proc/$(cat /www/server/nginx/logs/nginx.pid)/fd | grep log
    

    最后那条命令会列出 Nginx 进程当前打开的日志文件描述符,正常重开后应该指向新的 access.log。如果还指向已改名的旧文件,说明信号没生效或者配置里的路径和实际不符。

    表现三:切割正常但磁盘还是满。这时候问题往往不在切割本身,而是保留份数太多、单个日志太大,或者有别的大文件在占空间。rotate 14 意味着最多留 14 份归档,如果站点日均日志上 GB,压缩后依然可观,可以把 rotate 调小到 7。另外别只盯着 Nginx 日志,MySQL 的 binlog、PHP 的慢日志、面板自身的操作日志都可能吃掉大量空间,用 du -sh /www/* | sort -h 从大到小排一遍更直观。

    表现四:切割后网站报错或日志权限异常。多半是 create 参数里的属主和权限写得不对。切完手动 ls -l 看一下,和切割前保持一致即可。如果面板环境下不确定该用哪个用户,以 Nginx 配置里的 user 指令值为准。

    最后提一句,日志切割只是控制体积,不是减少写入。如果你发现日志增长速度异常快,比如一天几个 G,更值得做的是用 goaccess 或 awk 分析日志来源,看看是不是有异常请求在刷接口,从限速和封禁层面处理,这比一味加大保留份数更有效。

    总结一下操作顺序:先确认日志确实在写,再选 logrotate 手写配置或宝塔面板任务其中一种方式,配置里务必带上 postrotate 重开日志,然后用 logrotate -d 验证语法、-vf 手动跑一次看效果,最后检查归档文件的属主权限。做完这套,日志单文件占满磁盘的问题基本就解决了。下一步建议顺手把日志目录的磁盘占用加进监控,用 Uptime Kuma 或简单的 shell 脚本定时检查,让磁盘告警提前到你动手之前。

    继续阅读

    📑 📅
    宝塔面板网站目录权限怎么给:www用户与755/644取舍 2026-09-19
    Nginx上传目录禁止执行PHP:location匹配与fastcgi拦截写法 2026-09-18
    宝塔面板数据库连不上排查:socket与3306端口、bind-address区别 2026-09-18
    301跳转链太长拖慢首屏:curl与浏览器面板揪出重定向链 2026-09-18
    WordPress定时发布失效排查:wp-cron不触发与服务器计划任务替代方案 2026-09-18
    Cloudflare 后真实访客 IP 丢失:CF-Connecting-IP 与 Nginx real_ip 配置 2026-09-19
    WordPress改域名后打不开:siteurl与home改错的救援步骤 2026-09-19
    宝塔面板SSL证书部署后HTTP/2没生效:协议开启、ALPN检查与Nginx版本差异 2026-09-19
    WordPress邮件发不出去:wp_mail走SMTP还是sendmail与SPF/DKIM检查 2026-09-20
    宝塔面板FTP连不上:Pure-FTPd被动端口与权限排查 2026-09-20