但是,随着时间积累,业务增长,日志数量也是与日俱增,如果一个日志文件特别大的话,分析和存储都会很麻烦,所以会定期或定量将日志切割成一个个的小块(按时间,按大小),这样就比比较好存储,分析。
常见的切割方法,一般是自己写脚本,定时任务去运行,切割日志;或者使用 logroate 去自动的切割日志。logroate是一款linux预装的系统工具,系统日志都是通过logroate 去切割的。
很久以前,还问过一个同学 “你们的nginx日志是怎么切割的”,他说:“我们没切,大了就删了!!!”
不知道他后来,有没有被老板打死。
其实两种方法都是殊途同归,脚本和logroate 都只是切割的工具,“ 大家并没有问过为什么可以这么切,切割过程中,都做了哪些 ”,这里以logroate 为例,介绍下“切割的方式及实现”
Logroate 的运行流程:
前面说了可以写脚本用crond去触发,其实logroate也是通过crond触发的,看下面这个脚本:
[root@lastack ~]# 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
[root@lastack ~]#
这个脚本的主要任务,就是以 /etc/logrotate.conf 为配置文件,执行logroate,切割状态保存在 /var/lib/logrotate/logrotate.status 。
因为脚本在 /etc/cron.daily/ 下,所以是每天执行一次。
我们看配置文件:
[root@lastack ~]# cat /etc/logrotate.conf
# see "man logrotate" for details
# rotate log files monthly
monthly
# keep 4 weeks worth of backlogs
rotate 6
# 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
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 ,这个目录下是一些子配置文件,将不同日志的配置单独存放,这样便与管理,基本上一个服务对应配置一个文件。
[root@lastack ~]# cat /etc/logrotate.d/
bootlog chrony named syslog vsftpd wpa_supplicant yum nginx
[root@lastack ~]#
/data/nginx_logs/www.access.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 www www
sharedscripts
postrotate
if [ -f /data/nginx_logs/nginx.pid ]; then
kill -USR1 `cat /data/nginx_logs/nginx.pid
`
fi
endscript
}
相关参数:
- /data/nginx_logs/www.access.log # 要切割的文件路径,可以使用通配符, {}适用于这个文件的参数,可以写多个文件;
- daily 按天切割,此外还有 “ weekly,monthy,yearly”
- missingok 忽略切割过程中的错误;
- rotate 轮替最多保留之前的数据几次,超出的将被删除或邮件接收,设为0则不保存;
- compress 启用gzip压缩;
- delaycompress 通常与compress同用,指 最近的切割文件,不要压缩,下次切割时压缩,方便查看最近的日志;
- notifempty 如果日志文件为空,轮循不会进行;
- create 644 www www 创建新的日志文件,权限 644 属主 www,属组www;
- sharedscripts 表示多个日志文件之间滚动完成后,只通知一次;
- postrotate/endscript 在所有其它指令完成后,postrotate和endscript里面指定的命令将被执行。在这种情况下,rsyslogd 进程将立即再次读取其配置并继续运行。
这是些常用的参数,其他参数可以baidu下。
logroate的切割方式
上面的配置文件,定义了什么时候切割文件,这些切割都是为了实现,不影响应用的情况下,将大文件切割出来,下面说些怎么切:
在系统中,会为每个进程维护一个“文件信息表”,这个文件信息表中加载的是“这个进程所打开的所有文件”,而进程每打开一个文件,会在这个文件信息表中,添加一个指向这个文件inode的索引(中间的file dentry先不涉及)。
logroate 有两种切割方式:
CopyTruncate 方法
copytruncate 最是简单粗暴,其做法是
1.将一个正在写的日志文件内容拷贝出来,保存为滚动后的文件名(该压缩压缩);
2.直接清空前面那个正在写的日志文件。
这样拷贝前后日志文件的inode号没有变化,也不影响应用,就将大文件切割了。”
但是这样做有一个问题,如下:
程序A在向日志文件log.txt 写日志,已经写了100行了,这时logroate开始拷贝log.txt 到 log.txt-1 。而拷贝的过程中,程序A又写了 10行,这时拷贝完了,开始清空 log.txt , 那么刚才写的那10行也就一起清空了。新的日志文件记录的则是从第111行开始的。 这样会造成一些日志丢失,不过这也只是些日志,好像丢了10行也没大问题。
send signal 方法
这个方法就有意思了,说起来也很简单,其过程如下:
1. 程序A在写一个日志/var/log/file.log , logroate会将这个/var/log/file.log 给重命名 为/var/log/file.log-1 ,这个重命名过程中,修改的是/var/log 的block内容,更改的是inode对应的文件名,而这个文件file.log-1 和file.log 的 inode并没有变化,程序是根据inode写文件,所以不会影响日志写。
2. logroate创建一个新的日志文件/var/log/file.log,这个文件和前面 的/var/log/file.txt 文件路径相同,但是他们的inode不同。
3.logroate通知应用程序,重新加载配置,加载配置时,应用程序是通过文件系统找到 “ 文件路径/var/log/ ” 的block 接着找到 “ file.log ” 的 inode,这时候找到的则是新的inode,也就接着向新文件中写日志了。
这里的通知应用程序,是通过发送特定信号到程序, 就是这个了
有一个配置参数需要注意下:
sharedscripts ,如果一个程序输出了多个日志文件,而需要对这多个日志文件进行滚动,如果滚动一个,就通知程序重载配置,就有些麻烦了。所以 sharedscripts 这个参数,可以在滚动完这个程序的所有日志后,再通知程序。
https://www.hugbg.com/archives/627.html
2019-10-09 5:47 下午 1F
除了爱你,我什么都可以。 —《命运守护夜》
2019-10-09 5:56 下午 2F
喜欢和不讨厌之间可是有着数亿光年的距离的。 —《四月是你的谎言》
2019-10-10 10:38 上午 3F
对不起,风太大,我没有听清楚…… —《东京巴比伦》
2019-10-12 10:01 上午 4F
那似乎是比翼鸟。这种鸟天生单翼,须靠雌雄二鸟相互依偎才能翱翔天际,是种有缺陷的生物。但是,不知为何,我却感受到了这种生活方式的美妙。 —《Darling in the FRANXX》