前言

在使用linux的过程中,我们常常需要查询一些日志。但是如果某个日志文件过于庞大,包含了跨度时间很长的日志内容,那么我们的查询过程就会比较麻烦,好似大海捞针。

好在linux给我们提供了一种功能,可以将目标日志进行切割和分散,由此就使得查询到目标内容更加容易。

而最常用的一个linux工具,叫做logrotate,本文主要讲解此工具的用法。

 

logrotate

1 安装

# For Ubuntu/Debian
apt update & apt install -y logrotate

# For CentOS
yum update & yum install -y logrorate

# logrotate path
whereis logrotate

 

2 配置文件

默认的配置文件为:/etc/logrotate.conf, 默认包含以下内容(具体配置项内容过多,故略去部分):

# 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

# RPM packages drop log rotation information into this directory   处理RPM包主导的应用日志处理,比如Apache, nginx等
include /etc/logrotate.d

# no packages own wtmp and btmp -- we'll rotate them here   处理非RPM包主导的应用日志处理,例如系统日志
/var/log/wtmp {
···
}

/var/log/btmp {
 ···
}

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

 

3 定时运行

面对服务器,我们不可能每一次都手动去跑logrotate,因此它需要配合定时器(crontab)来跑。

好在linux提供了crontab的脚本:/etc/cron.daily/logrotate,每天运行一次。

[root@node1 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

 

4 添加配置项

上面的内容都是系统自动安排的,我们也没什么必要去做改变,但如果说我们需要对一个新的应用进行日志切割,我们在安装完之后,需要在配置项中做配置。

每安装一个包,它就会在include /etc/logrotate.d下添加一个配置项,我们可以直接在那里做配置(以nginx为例):

[root@node1 logrotate.d]# cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    create 0640 nginx root
    daily
    rotate 10
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

可以看到,它会规定相关的配置项,其中需要说明的是,postrotate需要给nginx的某个进程发送终止信号(USR1/USR2)后才可以重新启动一个log。

 

logrotate原理

logrotate属于热切割,即切割过程中并不影响正常的日志输出。

Linux文件操作机制

首先贴张介绍Linux的文件结构:

image

 

首先我们知道,目录也是文件,文件里存在两部分内容,一部分是inode索引,另一部分是文件内容。文件的inode可以查询文件本体的元数据,包括引用计数、操作权限、拥有者ID、创建时间、最后修改时间等。而文件名并不在元数据中,因此文件改名、移动,都不会改变文件,修改目录文件,也就是修改inode中的索引内容。

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

image

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

logrotate提供了两种方法去实现这种效果。

1. create(默认方案)
这个方案的思路是重命名原日志文件,并创建新的日志文件。具体步骤有三步:
1) 重命名正在输出的日志文件,因为重命名只改变目录及文件名称,而进程操作使用的是inode,所以并不影响原程序的输出。
2) 创建新的日志文件,保持文件名和原文件一致,但inode编号不同,故此文件初始为空。
3) 通过某些信号通知输出进程,重新打开日志文件。由于重新打开日志文件时只用到数据名并不用到inode,故新的日志会输出到步骤2创建的日志文件中,从而完成日志重定向。

好处:操作简单(mv+create),日志不会断

坏处:某些程序不提供重新打开日志文件的接口,而重启影响较大,故无法使用该方法。

 

2. copytruncate
这个方案的思路是将正在输出的日志拷贝一份出来,并清空原来的日志文件,使其重新写入。具体步骤有3步:
1) 将当前正在输出的日志copy一份出来,此时程序仍在写入原文件,原文件名称也没变。
2) 清空原日志文件,程序仍然会将日志输出到原文件,从而形成日志切割。

好处:兼顾了某些没有重新打开日志文件缺口程序的日志切割。

坏处:如果日志文件很大,copy时间很久,那么可能丢日志。

 

使用

logrotate的命令格式如下:

[root@node1 ~]# logrotate -?
用法: logrotate [OPTION...] <configfile>
  -d, --debug               Don't do anything, just test (implies -v)
  -f, --force               Force file rotation
  -m, --mail=command        Command to send mail (instead of `/bin/mail')
  -s, --state=statefile     Path of state file
  -v, --verbose             Display messages during rotation
  -l, --log=STRING          Log file
  --version                 Display version information

Help options:
  -?, --help                Show this help message
  --usage                   Display brief usage message

可以看到,最常用的功能是指定某个配置文件来用,常用选项也是-f的强制指定, 和-v的详细输出。
 
例如,我要手动切割nginx的日志,可以使用一下命令:

/usr/sbin/logrotate -vf /etc/logrotate.d/nginx

 
或者结合crontab使用。

crontab -e
*/30 * * * * /usr/sbin/logrotate /etc/logrotate.d/rsyslog > /dev/null 2>&1 &

 

也就可以了。

posted on 2022-05-14 23:54  eryoung2  阅读(1171)  评论(0编辑  收藏  举报