Linux日志收集logrotate原理介绍

Posted rayylee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux日志收集logrotate原理介绍相关的知识,希望对你有一定的参考价值。

前言

在Linux环境中能够帮助我们分析问题蛛丝马迹的有效办法之一便是日志,常见的如操作系统syslog日志/var/log/messages,应用程序nginx日志/var/log/nginx/*.log。但如果服务器数量较多,日志文件大小增长较快,不断消耗磁盘空间就会触发告警,如果需要人为定期按照各种维度去手动清理日志就显得十分棘手。为了节省空间和方便整理,可以将日志文件按时间或大小分成多份,删除时间久远的日志文件,这就是通常说的日志滚动(log rotation)。logrotate(GitHub地址) 诞生于 1996/11/19 是一个Linux系统日志的管理工具,本文会详细介绍Linux日志切割神器logrotate的原理和配置。

1. logrotate简介

logrotate ‐ rotates, compresses, and mails system logs

logrotate is designed to ease administration of systems that generate large numbers of log files. It allows automatic rotation, compression, removal, and mailing of log files. Each log file may be handled daily, weekly, monthly, or when it grows too large.

Normally, logrotate is run as a daily cron job. It will not modify a log more than once in one day unless the criterion for that log is based on the log’s size and logrotate is being run more than once each day, or unless the -f or --force option is used.

Any number of config files may be given on the command line. Later config files may override the options given in earlier files, so the order in which the logrotate config files are listed is important. Normally, a single config file which includes any other config files which are needed should be used. See below for more information on how to use the include directive to accomplish this. If a directory is given on the command line, every file in that directory is used as a config file.

If no command line arguments are given, logrotate will print version and copyright information, along with a short usage summary. If any errors occur while rotating logs, logrotate will exit with non-zero status.

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

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

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

2. logrotate运行机制

logrotate 在很多 Linux 发行版上都是默认安装的。系统会定时运行 logrotate,一般是每天一次。系统是这么实现按天执行的。crontab 会每天定时执行 /etc/cron.daily 目录下的脚本,而这个目录下有个文件叫 logrotate。在 centos 上脚本内容是这样的:

系统自带 cron task:/etc/cron.daily/logrotate,每天运行一次。

[root@gop-sg-192-168-56-103 logrotate.d]# cat /etc/cron.daily/logrotate
#!/bin/sh

/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0

可以看到这个脚本主要做的事就是以 /etc/logrotate.conf 为配置文件执行了 logrotate。就是这样实现了每天执行一次 logrotate。

因为我的系统执行 /etc/cron.daily 目录下的脚本不是我想滚动日志的时间,所以我把 /etc/cron.daily/logrotate 拷了出来,改了一下 logrotate 配置文件的路径,然后在 crontab 里加上一条指定时间执行这个脚本的记录,自定义周期滚动日志就大功告成了。这种自定义的方式有两点要注意:

  1. 配置文件里一定要配置 rotate 文件数目这个参数。如果不配置默认是 0 个,也就是只允许存在一份日志,刚切分出来的日志会马上被删除。多么痛的领悟,说多了都是泪。
  2. 执行 logrotate 命令最好加 -f 参数,不然有时候配置文件修改的内容不生效。

很多程序的会用到 logrotate 滚动日志,比如 nginx。它们安装后,会在 /etc/logrotate.d 这个目录下增加自己的 logrotate 的配置文件。logrotate 什么时候执行 /etc/logrotate.d 下的配置呢?看到 /etc/logrotate.conf 里这行,一切就不言而喻了。

include /etc/logrotate.d

3. logrotate原理

logrotate 是怎么做到滚动日志时不影响程序正常的日志输出呢?logrotate 提供了两种解决方案。 1. create 2. copytruncate

3.1 Linux 文件操作机制

介绍一下相关的 Linux 下的文件操作机制。

Linux 文件系统里文件和文件名的关系如下图。

img

目录也是文件,文件里存着文件名和对应的 inode 编号。通过这个 inode 编号可以查到文件的元数据和文件内容。文件的元数据有引用计数、操作权限、拥有者 ID、创建时间、最后修改时间等等。文件件名并不在元数据里而是在目录文件中。因此文件改名、移动,都不会修改文件,而是修改目录文件。

借《UNIX 环境高级编程》里的图说一下进程打开文件的机制。

img

进程每新打开一个文件,系统会分配一个新的文件描述符给这个文件。文件描述符对应着一个文件表。表里面存着文件的状态信息(O_APPEND/O_CREAT/O_DIRECT…)、当前文件位置和文件的 inode 信息。系统会为每个进程创建独立的文件描述符和文件表,不同进程是不会共用同一个文件表。正因为如此,不同进程可以同时用不同的状态操作同一个文件的不同位置。文件表中存的是 inode 信息而不是文件路径,所以文件路径发生改变不会影响文件操作。

3.2 create

这也就是默认的方案,可以通过 create 命令配置文件的权限和属组设置;这个方案的思路是重命名原日志文件,创建新的日志文件。详细步骤如下:

  1. 重命名正在输出日志文件,因为重命名只修改目录以及文件的名称,而进程操作文件使用的是 inode,所以并不影响原程序继续输出日志。
  2. 创建新的日志文件,文件名和原日志文件一样,注意,此时只是文件名称一样,而 inode 编号不同,原程序输出的日志还是往原日志文件输出。
  3. 最后通过某些方式通知程序,重新打开日志文件;由于重新打开日志文件会用到文件路径而非 inode 编号,所以打开的是新的日志文件。

如上也就是 logrotate 的默认操作方式,也就是 mv+create 执行完之后,通知应用重新在新文件写入即可。mv+create 成本都比较低,几乎是原子操作,如果应用支持重新打开日志文件,如 syslog, nginx, mysql 等,那么这是最好的方式。

不过,有些程序并不支持这种方式,压根没有提供重新打开日志的接口;而如果重启应用程序,必然会降低可用性,为此引入了如下方式。

3.3 copytruncate

该方案是把正在输出的日志拷 (copy) 一份出来,再清空 (trucate) 原来的日志;详细步骤如下:

  1. 将当前正在输出的日志文件复制为目标文件,此时程序仍然将日志输出到原来文件中,此时,原文件名也没有变。
  2. 清空日志文件,原程序仍然还是输出到预案日志文件中,因为清空文件只把文件的内容删除了,而 inode 并没改变,后续日志的输出仍然写入该文件中。

如上所述,对于 copytruncate 也就是先复制一份文件,然后清空原有文件。

通常来说,清空操作比较快,但是如果日志文件太大,那么复制就会比较耗时,从而可能导致部分日志丢失。不过这种方式不需要应用程序的支持即可。

以上是关于Linux日志收集logrotate原理介绍的主要内容,如果未能解决你的问题,请参考以下文章

Linux自带 Logrotate 日志切割工具配置详解

Linux下logrotate日志轮转操作梳理

利用Linux自带的logrotate管理日志

linux 日志定时轮询流程详解(logrotate)

linux下logrotate 配置和理解

对docker容器产生的日志做轮转