简单分享一下如何使用 logrotate 对 Rails 服务的日志进行切割与归档。
虽然 2021 年的今天,磁盘几乎是最不值钱的设备,但对于创业公司来说也不能大规模无脑去购买磁盘资源。于是一个不慎就会面临磁盘爆了的问题。磁盘一旦爆了,什么网站应用,数据库服务这些都会停止运行。
第一次磁盘被塞爆,主要是日志文件过大,因为前期访问量不大就没太在意这个问题,后面访问量大了,日志的增长速度加快,导致几十 G 的磁盘空间一下子就被塞满了。笔者也曾有过双手颤抖,把磁盘扩容,让服务重新运行的经历,那十来分钟,堪称地狱。
Linux 操作系统就有一个专门做日志切割与归档的工具logrotate。它的介绍如下
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.
简言之,它的作用就是周期性帮助维护者把日志切割成小份,并进行归档。
形象点说就是,假设你的日志文件所在的路径是/var/log/rails_production.log
。我们可以设置每天,每周甚至每个月对这个日志进行切割。也可以设置一个最大值,当日志文件超出我们所设置的阀值(假设说是 1G)的时候,日志就会被切割,生成一个名为/var/log/rails_production.log.1
的文件,这个文件主要存储一些比较老的日志。一段时间之后我们会得到一堆这样的日志
/var/log/rails_production.log(当前)
/var/log/rails_production.log.1
/var/log/rails_production.log.2
/var/log/rails_production.log.3
/var/log/rails_production.log.4
每生成一个/var/log/rails_production.log.X
被称作一个循环。我们可以设置 N 个循环过后清理一遍日志。假设我们设置为 5,那么我们其实最终只会保留/var/log/rails_production.log.[1~5]
5 个历史日志。更老的日志会自动被删除。
logrotate的配置相对比较简单,我只简单分享一下我们的配置
/var/www/yunchang/log/production.log {
daily
rotate 10
postrotate
kill -USR1 `cat /var/www/yunchang/tmp/pids/puma.pid`
endscript
compress
olddir /var/www/yunchang/log/old
}
Rails 的日志我一般存放在/var/www/yunchang/log/production.log
这个文件里面,上面配置的意思是即将对这个文件进行日志切割。切割周期是daily
也就是每天的凌晨 12 点进行日志切割。老日志会进行压缩compress
,并最终存放在目录/var/www/yunchang/log/old
底下。要是真想节约磁盘,请务必开启压缩选项。可以看看压缩前后的大小对比
> gunzip -c production.log.4.gz > production.log.4
> ls -hla production.log.4*
-rw-rw-r-- 1 deploy deploy 10G Oct 27 08:30 production.log.4
-rw-rw-r-- 1 deploy deploy 1.3G Oct 24 00:00 production.log.4.gz
10G 的日志经过压缩之后就剩大概 1.3G 左右。循环配置为rotate 10
,也就是说循环阀值为 10,每当旧的日志达到 10 个的时候会自动清理掉老的日志。这些都还算比较好理解,可能会有点蒙圈的是这个配置
postrotate
kill -USR1 `cat /var/www/yunchang/tmp/pids/puma.pid`
endscript
The lines between postrotate and endscript (both of which must appear on lines by themselves) are executed (using /bin/sh) after the log file is rotated.
这其实是一个嵌入脚本,每当日志切割之后就会运行一遍。因为 Rails 应用正在运行的过程中会持续往/var/www/yunchang/log/production.log
文件中写入日志资料。如果进程持续占用着这个文件,哪怕我们直接在磁盘上把这个文件删掉,由于进程还在,磁盘空间都无法得到释放。因此需要对 Puma 进行重启,这样新的进程会创建新的production.log
日志文件,跟老的日志完全脱钩,磁盘也将得到释放。Puma 重启的方式可以参见这份文档。
磁盘溢出并不是一件好玩的事情,一旦磁盘爆了所有服务都得重新启动。在业务运行的过程中最容易导致磁盘爆掉的要数日益增长的日志记录。加磁盘只是其中的一个手段,恰当地把日志进行压缩归档也不失为一个节省运营成本的做法,希望这篇文章对您有点帮助。