侧边栏壁纸
  • 累计撰写 59 篇文章
  • 累计创建 25 个标签
  • 累计收到 27 条评论

别让日志撑爆磁盘!Nginx日志优化实战:自动分片、定时归档、轻松管理亿级日志

heshaohua
2025-07-23 / 0 评论 / 0 点赞 / 21 阅读 / 1,077 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2025-08-02,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

项目上线时,在服务器搭建了nginx 环境后就开始运行了,没有设置 nginx 日志等配置,都是采用默认策略,日志存储位置:../nginx/logs/access.log,并且只会放在一个日志文件中,无法像 Logback 按日 期输出文件,导致 access.log 越来越大。Nginx 这些日志文件在悄无声息地膨胀,直到某一天,磁盘空间告急,应用异常宕机,还会导致占用服务器磁盘且排查日志时间长,搜索了一些解决方法后,整理成本文,希望此方案可以解决日志文件此类问题。

本文针对的是已经正在线上运行的 nginx 服务,如果是从零开始配置,直接跳到第4步、第5步即可。

1、关闭文件句柄占用

分片日志前把需要把历史文件清理,减少磁盘占用,如果需要历史文件记得请先备份文件。

先关闭 nginx 日志记录功能,在 /nginx/conf/nginx.conf 文件中 http 模块中 access_log 设置为 off,并重启 nginx ;

检查文件并重启命令:./nginx/sbin/nginx -t``./nginx/sbin/nginx -s reload

http {
    include       mime.types;
    default_type  application/octet-stream;
    ...
    access_log off;
    error_log off;    
    ...
}

重启完成后,检查该日志文件是否还有句柄占用(句柄占用就表示还有进程占用文件,即使删除文件也不生效,无法释放磁盘,所以需要先关闭进程),检查句柄占用的命令:lsof access.log,此时命令无内容输出就可以了。

2、清空历史日志

清空日志的命令:echo "" > access.log 。这条命令执行效率很高,清理60G的文件对系统性能毫无影响。

3、开启日志记录功能

日志清理完后,再把/nginx/conf/nginx.conf 文件中 http 模块中 access_log 直接注释掉再重启 nginx 就可以了。

http {
    include       mime.types;
    default_type  application/octet-stream;
    ...
    #access_log off;
    #error_log off;    
    ...
}

4、执行日志分片脚本

日志脚本 nginx_log_split.sh 放在 ../nginx/logs 下面,和 access.log 所在目录同级,需要给脚步可执行权限 chmod 774 nginx_log_split.sh

执行脚本就可看到效果,会自动创建 history_log 文件夹,会将日志文件按月份分文件夹,按天级别存储。如果线上访问量非常大的话,也可以按小时级别分片。

sh nginx_log_split.sh

#!/bin/bash
# 此处请设置nginx 绝对路径
nginx_home=/home/user/nginx/
nginx_log_path=${nginx_home}logs/
current_date=$(date +%Y-%m-%d)
access_log_file_name=access.log
error_log_file_name=error.log

history_file_path=${nginx_home}logs/history_log/$(date +%Y-%m)


# check if the nginx server alive
if [ -e ${nginx_log_path}nginx.pid ];then

    # create log folder for nginx log file
    if [ ! -e ${history_file_path} ];then
        mkdir -p ${history_file_path}
        echo "$(date) create folder success"
    fi


    # rename the log file with current date
    if [ -e $nginx_log_path$access_log_file_name ];then
        mv ${nginx_log_path}${access_log_file_name} ${history_file_path}/access-${current_date}.log
        echo "$(date) rename access.log successfully"
    else
        echo "$(date) access.log file no exist,skip"
    fi


    if [ -e $nginx_log_path$error_log_file_name ];then
        mv ${nginx_log_path}${error_log_file_name} ${history_file_path}/error-${current_date1}.log
        echo "$(date) rename error.log successfully"
    else
        echo "$(date) error.log file no exist,skip"
    fi

    # reopen the nginx server log
    ${nginx_home}/sbin/nginx -s reopen
    echo "$(date) reload log file success"

else
    echo "$(date) nginx server is close,skip"
fi

5、脚本设置定时执行

我们希望日志每天都能自动分片,每天拆分成一个文件,所以只需要设置脚本定时执行即可。Centos 有定时任务功能,设置 Corn 表达式,就会自动执行了。

查看当前的定时任务列表:crontab -l,编辑定时任务: crontab -e

每天23点59分分割日志

59 23 * * * /home/user/nginx/logs/nginx_log_split.sh > /home/user/nginx/logs/history_log/execute.log 2>&1

执行脚本的输出日志会重定向到 …/nginx/logs/history_log/execute.log 。

以上,Nginx 日志文件就实现自动分片,运行效果良好。 error.log 分片方法同上。

0

评论区