Nginx利用Logrotate实现日志分割


Posted in Servers onMay 20, 2022

前言

nginx默认没有提供对日志文件的分割功能,所以随着时间的增长,access.log和error.log文件会越来越大,尤其是access.log,其日志记录量比较大,更容易增长文件大小,影响日志写入性能

分割nginx日志的方法有很多,这里推荐利用Logrotate来完成

Logrotate用法

1.安装

logrotate是一个linux系统日志的管理工具。可以对单个日志文件或者某个目录下的文件按时间/大小进行切割,压缩操作;指定日志保存数量;还可以在切割之后运行自定义命令

logrotate是基于crontab运行的,所以这个时间点是由crontab控制的,具体可以查询crontab的配置文件/etc/anacrontab。系统会按照计划的频率运行logrotate,通常是每天。在大多数的Linux发行版本上,计划每天运行的脚本位于/etc/cron.daily/logrotate

主流Linux发行版上都默认安装有logrotate包,如果你的linux系统中找不到logrotate, 可以使用apt-get或yum命令来安装

yum install -y logrotate

一般linux都已经自带logrotate,下列命令可以查看是否已安装

rpm -ql logrotate

Nginx利用Logrotate实现日志分割

2.基本用法详解

2.1 入门

/etc/logrotate.conf这个文件是logrotate的主配置文件

# see "man logrotate" for details
# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
#compress

# 包含自定义配置目录
include /etc/logrotate.d

# no packages own wtmp and btmp -- we'll rotate them here
/var/log/wtmp {
    monthly
    create 0664 root utmp
        minsize 1M
    rotate 1
}

/var/log/btmp {
    missingok
    monthly
    create 0600 root utmp
    rotate 1
}

# system-specific logs may be also be configured here.

这个主配置文件中定义了日志文件分割的通用参数。并且include /etc/logrotate.d表示其会加载/etc/logrotate.d的所有自定义配置文件,自定义配置文件中的配置可以覆盖掉通用配置

我们来到自定义配置文件的目录/etc/logrotate.d

Nginx利用Logrotate实现日志分割

尝试在该目录中创建一个日志分割配置test,对/opt/logtest目录中所有以.log结尾的文件进行分割

vim test

# test配置文件的内容
/opt/logtest/*.log {
    daily
    rotate 2
    copytruncate
    missingok
}

test配置的第一行指定要对哪个路径的哪些文件进行分割,然后携带的4个参数解释如下:

  • daily:按天切割。触发切割时如果时间不到一天不会执行切割。除了daily,还可以选monthly,weekly,yearly
  • rotate:对于同一个日志文件切割后最多保留的文件个数
  • copytruncate:将源日志文件切割成新文件后,清空并保留源日志文件。默认如果不启用该配置,分割后源日志文件将被删除。设置该值,以便分割后可以继续在源日志文件写入日志,等待下次分割
  • missingok:切割中遇到日志错误忽略

创建好配置以后,系统会在每天利用cron定时执行logrotate日志分割指令。这里我们为了看到效果,不等到系统自动执行,可以手动强制执行一次日志分割。强制执行会立即进行一次日志

# -v:显示执行日志
# -f:强制执行分割
logrotate -vf /etc/logrotate.d/test

执行前,事先在日志所在目录中创建2个测试日志文件

touch test1.log
touch test2.log

手动执行一次日志分割,观察执行日志可以发现,过程如下:

  • 先将源日志内容拷贝到分割后的文件
  • 清空源文件

Nginx利用Logrotate实现日志分割

此时分割后的文件名为源文件名后面加上.序号,序号从1开始

Nginx利用Logrotate实现日志分割

然后我们再次手动执行一次分割,此时执行过程如下:

  • 将第一次分割后的日志文件test1.log.1重命名为test1.log.2
  • 将源日志文件拷贝到此次分割后的文件,命名序号重新从1开始,为test1.log.1
  • 清空源日志文件

Nginx利用Logrotate实现日志分割

Nginx利用Logrotate实现日志分割

接着再次手动执行一次分割,此时执行过程如下:

  • 将之前分割后的日志文件test1.log.2重命名为test1.log.3,test1.log.1重命名为test1.log.2
  • 分割源日志文件,拷贝其内容到test1.log.1
  • 由于设置了rotate为2,即最多保留2个日志文件,所以此时要删除最早分割出的那个日志文件,即test1.log.3

Nginx利用Logrotate实现日志分割

Nginx利用Logrotate实现日志分割

总结一下logrotate日志分割的步骤:

1.默认分割后日志的命名为源日志名称+.序号(从1开始)。分割之前将所有之前分割出的日志文件重命名,序号往后移一位
2.执行分割,将源日志文件分割为源日志文件名.1。这样就保证了所有分割后的文件中,序号最小的是最新分割出的,序号最大的是最早分割出的
3.根据rotate设置,如果此次分割后文件数量大于rotate设置,那么删除序号最大的那个分割文件,也就是最旧的分割日志

实际开发中可以使用create代替copytruncate,它们的区别如下:

copytruncate先将源文件内容拷贝到分割后文件,再清空源文件,拷贝和清空之间有时间差,可能会丢失部分日志。另外拷贝操作在源文件比较大时消耗性能

create直接将源文件重命名为分割后文件,再创建一个与源文件名称相同的新文件,用于后续日志写入

/opt/logtest/*.log {
    daily
    rotate 2
    create  # 创建与源文件名称相同的新文件,用于后续日志写入,新文件的归属用户、权限与源文件相同
    missingok
}

Nginx利用Logrotate实现日志分割

但是要注意create即使创建新的文件后,如果没有主动通知应用程序,那么应用程序仍然会往旧的文件(即被重命名的那个分割后的文件)写入日志。所以此时在分割后要通知应用程序重新打开新的日志文件进行写入。以通知nginx为例,配置如下

/var/log/nginx/*.log {
    daily                      
    rotate 30              
    create
    sharedscripts              # 所有的文件切割之后只执行一次下面脚本,通知nginx重新打开新的日志文件进行后续写入
    postrotate
        if [ -f /run/nginx.pid ]; then
            kill -USR1 `cat /run/nginx.pid`  # 通过USER1信号通知nginx重新打开日志文件
        fi
    endscript
}

综上,一般情况下如果应用程序提供了通知其打开新的日志文件的接口,那么推荐使用create续写日志;否则推荐使用copytruncate续写日志

注意:

  • /etc/logrotate.d中的自定义配置中,如果不配置rotate、daily等参数在强制手动执行时并不会继承默认的主配置/etc/logrotate.conf。比如不配置rotate时,并不会继承保留4个分割文件,而是等价于0,即不保留任何分割文件。所以自定义配置中推荐显式指定这些参数
  • 在系统crontab定时任务自动执行logrotate时,自定义配置会继承主配置文件中的参数
  • logrotate执行分割的时机要依赖于crontab定时任务,也就是说crontab定时任务每日触发时,logrotate才会读取相应配置,检查是否满足分割的条件决定是否执行分割。这意味着,在默认crontab每日触发logrotate的定时任务情况下,即便logrotate配置文件中配置的分割频率小于1天,也将按照1天的频率触发分割,除非修改crontab定时任务,将logrotate的任务触发频率修改为小于1天

2.2 分割文件压缩

我们可以通过如下设置对分割后的日志文件开启压缩

/opt/logtest/*.log {
    daily
    rotate 2
    copytruncate
    missingok
    compress           # 以gzip方式压缩
    nodelaycompress    # 所有分割后的文件都进行压缩
}

此时删除原有所有文件,重新创建测试日志文件test1.log和test2.log,然后手动执行分割,可以生成压缩后的.gz文件

Nginx利用Logrotate实现日志分割

一般可以将nodelaycompress改为delaycompress,这样分割后对最新的序号为1的文件不会进行压缩,对其他序号的文件进行压缩,这样可以方便我们查看最新的分割日志

Nginx利用Logrotate实现日志分割

2.3 按照时间分割

按照时间分割可以定时分割出一个日志,比如每天分割一次,配合其他参数可以完成保留最近n天日志的功能。以下配置可以实现每天分割一次日志,并且保留最近30天的分割日志

/opt/logtest/*.log {
    daily      # 每天分割一次
    rotate 30  # 保留最近30个分割后的日志文件
    copytruncate
    missingok
    dateext  # 切割后的文件添加日期作为后缀
    dateyesterday # 配合dateext使用,添加前一天的日期作为分割后日志的后缀
}

还是先删除原来的所有文件,重新创建

touch test{1,2}.log

再手动执行分割,此时生成的分割后的文件将不再以序号作为文件名结尾,而是以昨天的日期作为结尾

Nginx利用Logrotate实现日志分割

并且如果马上再手动执行一次分割,由于日期相同,不会像原来一样生成序号递增的新日志文件,此时相当于没有执行任何分割操作。即同一天只能分割一次,第二天再次执行才会分割出新的日期结尾的文件,所以此时设置rotate的值即为保留最近多少天日志的意思

Nginx利用Logrotate实现日志分割

此外,默认添加的日期后缀格式为yyyyMMdd,可以用dateformat自定义

/opt/logtest/*.log {
    daily      # 每天分割一次
    rotate 30  # 保留最近30个分割后的日志文件
    copytruncate
    missingok
    dateext  # 切割后的文件添加日期作为后缀
    dateyesterday # 配合dateext使用,添加前一天的日期作为分割后日志的后缀
    dateformat -%Y-%m-%d  # 格式为2022-02-08
}

2.4 按照文件大小分割

我们可以利用size配置指定当日志文件达到多大体积时才进行分割。以下配置指定了每天执行分割,但是只有当日志文件大于5M时才真正执行分割操作

/opt/logtest/*.log {
    daily      # 每天分割一次
    size 5M    # 源文件小于5M时不分割
    rotate 30  # 保留最近30个分割后的日志文件
    create
    missingok
    dateext  # 切割后的文件添加日期作为后缀
    dateyesterday # 配合dateext使用,添加前一天的日期作为分割后日志的后缀
}

注意:这个配置并不是说日志文件达到指定大小就自动执行分割,它还是要遵循定时任务。比如配置了daily只有到每天指定时间执行分割任务时,才会检查文件大小,对超过指定大小的文件进行分割

2.5 自定义每小时分割

logrotate实现每日定时执行日志分割的原理是通过cron定时任务,默认在/etc/cron.daily中包含logrotate可执行命令,所以系统每天会定时启动logrotate,然后它会根据配置中具体分割频率(daily、weekly等)以及其他条件(比如size)决定是否要真正执行分割操作

Nginx利用Logrotate实现日志分割

如果我们想要实现每小时进行一次分割,需要如下步骤:

  1. logrotate配置文件中指定分割频率为hourly
  2. 配置完以后,还需要在cron的每小时定时任务中加入logrotate,因为默认情况下只有/etc/cron.daily中包含logrotate可执行命令,我们要将它往/etc/cron.hourly中也拷贝一份,这样系统才会每小时调用一次logrotate去执行分割
cp /etc/cron.daily/logrotate /etc/cron.hourly/

2.6 自定义分割执行时间

logrotate 是基于cron 运行的,所以这个时间是由 cron 控制的,具体可以查询 cron 的配置文件/etc/crontab 。旧版CentOS 的cron 的配置文件是 /etc/crontab ,新版CentOS 改为 /etc/anacrontab

Nginx利用Logrotate实现日志分割

从上面的内容可以看出:

  • 如果机器 没有关机,默认 logrotate(配置文件里设置的是cron.daily)一般会在每天的3点05分到3点50分之间执行, 真实的延迟时间是RANDOM_DELAY + delay in minutes
  • 如果在3-22 这个时间段内服务器处于 关机状态,则 logrotate 会在机器开机5分钟后执行分割日志的操作

如果我们觉得每天凌晨3点多执行日志分割不合适,那么可以自定义分割执行时间。实现方式可以是:

  • 修改/etc/anacrontab中的定时执行时间,实际不推荐,可能会影响系统其他定时任务
  • 在/etc/logrotate.d以外的其他目录创建logrotate配置文件,然后利用crontab自定义cron表达式来执行logrotate对该配置进行分割操作

推荐采用crontab方式自定义执行时间,步骤如下:

在非/etc/logrotate.d目录创建logrotate配置文件,这是为了避免被系统的定时任务扫描到该配置而导致重复执行分割

添加 crontab 计划任务,在 root 用户下执行crontab -e进入 vim 模式,进行编辑

crontab -e
# 每天 23点59分进行日志切割
59 23 * * * /usr/sbin/logrotate -f /etc/logrotate_mytime/nginx

重启crontab

# centos6: 
service crond restart

# centos7: 
systemctl restart crond

nginx日志分割步骤

在/etc/logrotate.d中创建文件nginx,作为nginx日志分割的配置文件。指定每天执行一次分割,并且当文件大于5M时才进行分割。同时指定notifempty,当日志文件为空时不分割

/opt/docker-ws/nginx/logs/*.log {
    daily      # 每天分割一次
    size 5M    # 源文件小于5M时不分割
    rotate 30  # 保留最近30个分割后的日志文件
    copytruncate
    notifempty # 当日志文件为空时不分割
    missingok
    dateext  # 切割后的文件添加日期作为后缀
}

这样配置了以后系统会在凌晨3点多执行分割操作,执行结果会保存到/var/spool/mail/root中

Nginx利用Logrotate实现日志分割

查看结果发现提示权限不够而分割失败,这是因为开启了selinux导致,解决方案有如下2种:

1、关闭selinux/2、利用semanage修改待分割的日志文件所在目录的权限

# 开放/opt/logtest目录的权限
semanage fcontext -a -t var_log_t "/opt/logtest(/.*)?"
restorecon -Rv /opt/logtest

总结

到此这篇关于Nginx利用Logrotate日志分割的文章就介绍到这了!


Tags in this post...

Servers 相关文章推荐
Nginx tp3.2.3 404问题解决方案
Mar 31 Servers
nginx常用配置conf的示例代码详解
Mar 21 Servers
nginx配置限速限流基于内置模块
May 02 Servers
鲲鹏 CentOS 7 安装Python3.7
May 11 Servers
关于windows server 2012 DC 环境 重启后蓝屏代码:0xc00002e2的问题
May 25 Servers
nginx rewrite功能使用场景分析
May 30 Servers
Apache POI操作批量导入MySQL数据库
Jun 21 Servers
Windows Server 2022 超融合部署(图文教程)
Jun 25 Servers
windows server 2016 域环境搭建的方法步骤(图文)
Jun 25 Servers
Windows Server 2008配置防火墙策略详解
Jun 28 Servers
ssh服务器拒绝了密码 请再试一次已解决(亲测有效)
Aug 14 Servers
nginx lua 操作 mysql
May 15 #Servers
Nginx HTTP跳转至HTTPS
Nginx 匹配方式
May 15 #Servers
nginx实现多geoserver服务的负载均衡
May 15 #Servers
Nginx 常用配置
鲲鹏 CentOS 7 安装Python3.7
May 11 #Servers
在容器中使用nginx搭建上传下载服务器
May 11 #Servers
You might like
一个用于mysql的数据库抽象层函数库
2006/10/09 PHP
php实现文件下载更能介绍
2012/11/23 PHP
淘宝ip地址查询类分享(利用淘宝ip库)
2014/01/07 PHP
PHP/HTML混写的四种方式总结
2017/02/27 PHP
PHP+Redis链表解决高并发下商品超卖问题(实现原理及步骤)
2020/08/03 PHP
javascript multibox 全选
2009/03/22 Javascript
jQuery 获取/设置/删除DOM元素的属性以a元素为例
2014/05/23 Javascript
js字符串完全替换函数分享
2014/12/03 Javascript
简单谈谈javascript代码复用模式
2015/01/28 Javascript
IE7浏览器窗口大小改变事件执行多次bug及IE6/IE7/IE8下resize问题
2015/08/21 Javascript
js剪切板应用clipboardData实例解析
2016/05/29 Javascript
jQuery动态添加与删除tr行实例代码
2016/10/18 Javascript
layer实现弹窗提交信息
2016/12/12 Javascript
ztree实现左边动态生成树右边为内容详情功能
2017/11/03 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
vue-cli项目代理proxyTable配置exclude的方法
2018/09/20 Javascript
python解析文件示例
2014/01/23 Python
Python中join和split用法实例
2015/04/14 Python
Python基于回溯法解决01背包问题实例
2017/12/06 Python
python通过TimedRotatingFileHandler按时间切割日志
2019/07/17 Python
使用批处理脚本自动生成并上传NuGet包(操作方法)
2019/11/19 Python
Python有参函数使用代码实例
2020/01/06 Python
对Matlab中共轭、转置和共轭装置的区别说明
2020/05/11 Python
python实现126邮箱发送邮件
2020/05/20 Python
PyCharm配置anaconda环境的步骤详解
2020/07/31 Python
python脚本使用阿里云slb对恶意攻击进行封堵的实现
2021/02/04 Python
详解css3 mask遮罩实现一些特效
2018/10/24 HTML / CSS
瑰珀翠美国官网:Crabtree & Evelyn美国
2016/11/29 全球购物
美国唇部护理专家:Sara Happ
2019/06/19 全球购物
澳大利亚领先的亚麻品牌:Bed Threads
2019/12/16 全球购物
应届生船舶驾驶求职信
2013/10/19 职场文书
《两只鸟蛋》教学反思
2014/02/10 职场文书
销售员岗位职责
2015/02/10 职场文书
上班迟到检讨书
2015/05/06 职场文书
公司保密管理制度
2015/08/04 职场文书
银行客户经理培训心得体会
2016/01/09 职场文书