微端大带宽服务器日志过大占满磁盘?
对于微端业务来说,日志文件的大小往往是个让人头疼的问题。我自己就见过不少厦门机房里跑微端游戏的服务器,因为日志没管好,磁盘被写满,结果游戏更新发不出去,玩家卡在登录界面进不来。这篇文章我想跟你聊聊这个事儿,说说日志是怎么把磁盘撑爆的,更重要的是,怎么用顺手的方法把这个问题解决掉。
一、日志是怎么悄悄把磁盘吃光的
先讲一个真实发生过的案例。去年有个做微端页游联运的朋友,服务器放在厦门某机房,带宽开得挺大,玩家在线数也不错。有一天半夜,运维监控突然报警,说一台游戏更新服务器磁盘使用率达到百分之九十八。他登录上去一看,结果发现是Nginx的access日志单个文件已经涨到了四十多个G。
为什么会有这么大的日志呢?因为微端业务的特点就是请求密集。一个玩家从打开登录器到进入游戏,中间可能要拉取几十甚至上百个小文件。再加上厦门大带宽机房普遍网络质量好,请求量自然就上去了。每一笔请求都会在access.log里留下一行记录,日积月累,这个文件就像滚雪球一样越来越大。
更要命的是,很多服务默认的日志配置是“一直写,写到天荒地老”。没有人告诉系统说,日志文件到了多大就该换个地方写。结果就是,一个几十G的日志文件躺在磁盘上,不光占地方,你用less或者vim去打开它,机器都要卡半天。更别提从里面grep点什么东西出来,简直是在折磨自己。
二、不切割日志会带来哪些麻烦
日志不切割,问题可不只是“磁盘满了”这么简单。
第一个麻烦是排查问题变得特别困难。假设游戏某个时段出了故障,你想查一下那个时间段的错误日志。结果日志文件有三十个G,你用grep去搜,运气好的话等个几分钟,运气不好直接内存撑爆。更别说用普通文本编辑器打开了,根本打不开。
第二个麻烦是日志轮转失效。很多程序写日志的时候,是打开一个文件句柄一直往里写的。如果你直接把这个文件删了或者移走了,程序不会自动去建一个新的日志文件,它还在往原来的文件句柄里写。这就好比你搬家的时候把旧地址的邮箱撤了,但邮递员还往那儿送信,信就丢了。
第三个麻烦是备份和迁移变得不现实。有些业务场景要求保留一段时间的日志用于审计或者用户行为分析。如果日志不切割,你每天要备份的是一个几十G的大文件,传也传不动,存也存不起。切割之后变成按天的小文件,备份起来就轻松多了。
三、logrotate:大多数人不知道的日志切割神器
关于日志切割,Linux系统里其实已经自带了一个非常好用的工具,叫logrotate。很多朋友可能没注意过它,但它一直在后台默默工作着。
logrotate的配置主要分两块。一块是主配置文件,在/etc/logrotate.conf,这里面定义了全局的默认规则,比如每周切割一次、保留四个轮换文件、是否压缩等等。另一块是针对具体服务的配置文件,放在/etc/logrotate.d/目录下。这个设计很合理,每个服务可以有自己的切割策略,互不干扰。
举个例子,假设你的微端服务器用的是Nginx,日志放在/var/log/nginx/下面。你可以在这个目录下创建一个配置文件,告诉logrotate怎么处理这些日志。一个典型的配置大概是这个样子的:
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 www-data www-data
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
我们一条一条来看这些配置的含义。daily表示每天切割一次,也就是每天凌晨的时候把前一天的日志挪走,新建一个日志文件继续写。missingok的意思是如果日志文件不存在,没关系,跳过就行,不用报错。rotate 30表示保留三十个轮换文件,也就是大约一个月的日志。compress是说把轮换下来的旧日志用gzip压缩一下,这样可以省下不少磁盘空间。delaycompress和compress配合使用,意思是刚刚轮换的那个文件先不压缩,等到下一次轮换的时候再压缩,这样如果程序还在往旧文件里写东西,也不会出问题。
sharedscripts是一个容易被忽略但很关键的参数。它的作用是,在轮换日志之前或之后执行脚本的时候,只执行一次,而不是对每个匹配到的日志文件都执行一次。对于Nginx来说,postrotate里面那段脚本的作用是给Nginx进程发一个USR1信号,告诉它重新打开日志文件。如果不做这一步,Nginx还会继续往已经改名的旧文件里写日志。
四、动手配置:从零开始给微端服务器加日志切割
说了这么多,我们来实际操作一下。假设你的微端服务器上跑着Nginx和游戏服务端,日志都写在/var/log/下面。
第一步,先看看系统里有没有安装logrotate。大多数Linux发行版默认都带了,你可以运行这个命令检查一下:
logrotate --version
如果提示命令没找到,安装也很简单。CentOS上用yum install logrotate,Ubuntu上用apt-get install logrotate。
第二步,在/etc/logrotate.d/目录下新建一个配置文件,比如就叫game。用vim或者其他编辑器打开这个文件,写入刚才说的那些配置。注意把路径改成你实际的日志路径。
第三步,手动测试一下配置是否生效。logrotate提供了一个调试模式,可以模拟运行而不实际改动文件:
logrotate -d /etc/logrotate.d/game
如果输出没有报错,说明配置语法没问题。然后你可以强制执行一次看看效果:
logrotate -vf /etc/logrotate.d/game
-v是显示详细过程,-f是强制执行,不管有没有到切割时间都切一次。
第四步,检查切割结果。执行完之后,去你的日志目录看看,原来的日志文件应该被重命名成了类似access.log-20250101这样的格式,然后生成了一个全新的空白的access.log文件。如果看到压缩后的.gz文件,说明compress参数也生效了。
第五步,确认定时任务。logrotate本身不自带定时器,它是靠系统的cron来触发的。通常在/etc/cron.daily/目录下会有一个logrotate的脚本,系统每天会执行一次。如果你的日志需要更频繁的切割,比如每小时一次,可以在/etc/cron.hourly/里添加相应的配置,或者在crontab里单独指定。
五、进阶玩法:按大小切割和按需压缩
除了按时间切割,logrotate还支持按文件大小切割。这个功能对于流量忽大忽小的微端业务来说特别实用。有时候搞活动,流量翻好几倍,日志长得飞快,等不到每天一次的切割,磁盘可能就满了。
配置按大小切割很简单,在配置里加上size这个参数就行。比如size 100M,表示日志文件达到一百兆的时候就触发切割。你可以把size和daily放在一起用,哪个条件先满足就按哪个来。
还有一个实用的参数是maxsize。它和size的区别在于,size不管时间到了没有,只要文件大小超过阈值就切;而maxsize是在切割周期内,如果文件超过这个大小就提前切。举个例子,你设置了daily和maxsize 200M,正常情况下每天切一次,但如果某天的日志半天就超过了200M,系统会立即切一次,避免日志文件过大。
关于压缩,需要留意的是delaycompress这个参数。为什么要有它呢?因为有些服务在日志轮换之后,可能不会立刻切换到新文件,还会往旧文件里写一小段时间的数据。如果你立刻把旧文件压缩了,这些数据就写不进去了。delaycompress的作用就是等到下一次轮换的时候,再把上一次的文件压缩,给程序留足了缓冲时间。
六、需要注意的几个坑
日志切割虽然不算复杂,但有几个坑确实容易踩到,我说出来给大家提个醒。
第一个坑是copytruncate参数的使用场景。有些程序不支持重新打开日志文件的信号,比如一些老旧的Java应用。这时候可以用copytruncate的方式:先把当前日志文件复制一份作为备份,然后用truncate命令把原文件清空。这样程序还在往同一个文件句柄里写,感觉不到任何变化。但这个方案有个小问题,复制和清空之间有一个极短的时间差,可能会丢失几行日志。对于微端业务来说,这几行日志可能恰好是关键的报错信息,所以能不用copytruncate就尽量不用。
第二个坑是权限问题。logrotate在创建新日志文件的时候,是用什么用户和权限创建的,取决于create参数。如果不指定,可能会用默认的root权限,导致原来写日志的程序没有权限写入新文件。所以在配置里最好明确写出create 0640 用户名 组名这样的信息。
第三个坑是postrotate脚本的健壮性。脚本里面如果用了kill命令,最好加上2>/dev/null把错误输出丢掉,再在末尾加上|| true,避免脚本因为找不到进程而报错退出。这样即使Nginx没在运行,logrotate也能正常完成。
七、微端业务特有的日志策略建议
微端业务和普通网站不太一样,它的日志有几个特点。一个是短连接请求特别多,每次拉取一个几KB的小文件就是一次请求,access日志行数非常密集。另一个是高峰期流量起伏大,晚上和周末的日志量可能是平时的好几倍。
针对这些特点,我个人的建议是这样。
切割频率可以设置成按小时切,而不是按天。因为微端日志行数多,一天的日志可能轻松上十个G,用grep查起来很不方便。切成小时文件,每个文件几百兆,查起来就快多了。配置也很简单,把daily改成hourly就行。不过要注意,logrotate默认的cron.daily只执行一次,想用hourly的话需要自己在crontab里配置。
保留周期可以根据业务需求来定。一般保留七天到三十天就够了,再老的日志可以压缩归档到其他存储。配置里用rotate 168就可以保留一周的小时日志(一天24小时乘以7天)。
压缩一定要开,而且可以用gzip的最高压缩比。微端日志里重复的模式很多,压缩比往往能达到一比十甚至更高,一百兆的日志压完可能只剩十兆。
最后,建议把error日志和access日志分开处理。access日志量大,可以切割频繁一些,保留时间短一些。error日志量小但重要,可以保留时间长一点,比如三个月甚至半年。
八、总结
厦门大带宽服务器跑微端业务,带宽大、流量猛,日志自然也跟着疯长。日志切割不是锦上添花的事儿,而是必须做的基础运维工作。不切日志,磁盘迟早被撑爆,到时候玩家登录不上、游戏更新发不出,损失的就不只是时间和精力了。
logrotate这个工具,说简单也简单,就是写个配置文件,让它定时跑起来。说复杂也复杂,那些参数的含义、执行脚本的时机、权限的设置,每一条都对应着实际运维中可能遇到的问题。理解了这些背后的逻辑,你就能根据自己的业务特点,定制出最合适的切割策略。
如果你现在还没给自己的服务器配上日志切割,不妨今天就动手试试。从写一个最简单的配置文件开始,测试一下,加到cron里跑起来。这个过程花不了多少时间,但它能让你的服务器更健康地跑下去。毕竟,对于微端业务来说,稳定就是生命线。一个磁盘被日志塞满导致服务停摆的夜晚,没有人想经历第二次。


