2. Linux日志系统:rsyslog配置、日志轮转、journalctl使用与采集策略
日志这东西,平时没人搭理它。一旦线上出故障,它就是唯一的救命稻草。我做了这么多年运维,最怕的就是登录服务器一看——日志文件是空的,或者被撑爆了。嗯,今天咱们就把Linux日志系统这块彻底捋清楚。
2.1 rsyslog:日志界的瑞士军刀
rsyslog是Linux上最主流的日志收集守护进程。说白了,它就是个智能快递员——把系统里各种程序产生的日志消息,按照你定的规则,送到该去的地方。
它的配置文件在 /etc/rsyslog.conf 和 /etc/rsyslog.d/ 目录下。我个人习惯把自定义规则写在 /etc/rsyslog.d/ 里,这样升级主配置时不会被覆盖。
2.1.1 配置语法速览
rsyslog的规则格式其实很简单:
设施.级别 动作
举个例子:
# 把所有内核日志写到 /var/log/kern.log
kern.* /var/log/kern.log
# 把mail相关的所有级别日志写到单独文件
mail.* /var/log/mail.log
# 把紧急级别的日志发送到所有登录用户的终端
*.emerg :omusrmsg:*
这里有个坑——设施和级别的对应关系。设施包括 auth、cron、daemon、kern、mail、syslog、user 等。级别从低到高是 debug、info、notice、warning、err、crit、alert、emerg。
*.=info 表示只匹配info级别,用 *.info 表示匹配info及以上所有级别。这个等号很关键,我在项目中见过有人搞混,结果日志量翻了好几倍。
2.1.2 远程日志收集
生产环境里,我强烈建议把日志集中到一台服务器上。这样排查问题时不用挨个登录机器。
服务端配置(接收日志):
# 在 /etc/rsyslog.conf 中取消注释
$ModLoad imudp
$UDPServerRun 514
$ModLoad imtcp
$TCPServerRun 514
# 接收到的日志按来源IP分类存储
$template RemoteLogs,"/var/log/remote/%fromhost-ip%/%programname%.log"
*.* ?RemoteLogs
客户端配置(发送日志):
# 在 /etc/rsyslog.d/remote.conf 中
*.* @192.168.1.100:514 # UDP发送
*.* @@192.168.1.100:514 # TCP发送
2.2 日志轮转:别让日志撑爆磁盘
日志如果不轮转,一个月就能把磁盘塞满。我见过最夸张的一次,某台机器上 /var/log/messages 达到了80GB,系统直接卡死。
Linux下日志轮转靠的是 logrotate。它的配置文件在 /etc/logrotate.conf 和 /etc/logrotate.d/ 目录下。
2.2.1 核心配置项
| 配置项 | 说明 | 示例 |
|---|---|---|
| daily/weekly/monthly | 轮转周期 | daily |
| rotate N | 保留N个历史文件 | rotate 7 |
| compress | 压缩旧日志 | compress |
| maxsize SIZE | 日志超过SIZE就轮转 | maxsize 100M |
| missingok | 日志文件不存在不报错 | missingok |
| notifempty | 空文件不轮转 | notifempty |
| postrotate/endscript | 轮转后执行的脚本 | 重启服务 |
来看一个实际例子:
/var/log/nginx/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
maxsize 200M
sharedscripts
postrotate
/bin/kill -USR1 `cat /var/run/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
这里有个细节——delaycompress。它的意思是这次轮转不立即压缩,等下次轮转再压缩。为什么?因为有些程序还在往旧文件里写数据,立即压缩可能导致数据丢失。嗯,这个坑我踩过。
2.2.2 手动测试轮转
配置写好了,别直接等cron执行。先手动跑一下看看效果:
# 强制轮转,但不实际执行
logrotate -d /etc/logrotate.d/nginx
# 强制轮转,实际执行
logrotate -f /etc/logrotate.d/nginx
2.3 journalctl:systemd时代的日志神器
从CentOS 7/RHEL 7开始,systemd接管了系统初始化,同时也带来了 journald 日志系统。它的日志存在 /var/log/journal/ 目录下,是二进制格式,不能直接用cat看。得用 journalctl 来查。
2.3.1 常用查询技巧
# 查看所有日志
journalctl
# 查看本次启动以来的日志
journalctl -b
# 查看上次启动的日志
journalctl -b -1
# 查看某个服务的日志
journalctl -u nginx.service
# 查看最近5分钟的日志
journalctl --since "5 min ago"
# 按优先级过滤(0=emerg, 1=alert, 2=crit, 3=err, 4=warning...)
journalctl -p err -b
# 实时跟踪日志(类似tail -f)
journalctl -f -u nginx.service
我个人最常用的组合是:
# 查看某个服务最近一小时的错误日志
journalctl -u nginx.service --since "1 hour ago" -p err --no-pager
2.3.2 日志持久化
默认情况下,journald的日志存在内存里,重启就没了。想持久化?很简单:
# 创建持久化目录
mkdir -p /var/log/journal
# 重启服务
systemctl restart systemd-journald
然后编辑 /etc/systemd/journald.conf:
[Journal]
Storage=persistent
Compress=yes
MaxRetentionSec=1month
MaxFileSec=1week
SystemMaxUse=1G
SystemMaxUse 设为1GB或2GB,防止journald把磁盘撑爆。另外,MaxRetentionSec 设成1个月,太老的日志该删就删。
2.4 日志采集策略:从源头到平台
讲完了工具,咱们聊聊策略。日志采集不是把日志文件扔给采集器就完事了。你得想清楚几个问题。
2.4.1 采集什么
不是所有日志都要采。我见过有人把 /var/log/debug 也采到ELK里,结果一天几个TB,查询还巨慢。我的建议是:
- 必采: 系统日志(messages、secure)、应用访问日志、错误日志
- 按需采: 慢查询日志、审计日志、性能日志
- 不采: debug日志、重复的轮转旧文件
2.4.2 采集方式
目前主流的采集方式有三种:
| 方式 | 工具 | 适用场景 | 优缺点 |
|---|---|---|---|
| Agent采集 | Filebeat、Logstash | 通用场景 | 灵活、资源占用可控 |
| Syslog转发 | rsyslog、syslog-ng | 网络设备、旧系统 | 配置简单、但功能有限 |
| API采集 | 自定义脚本 | 云服务、特殊格式 | 定制化强、但维护成本高 |
我个人推荐用Filebeat + rsyslog的组合。Filebeat负责采集文件,rsyslog负责接收syslog。这样既覆盖了文件日志,也覆盖了系统日志。
2.4.3 避坑指南
- 采集器权限不够,读不到日志文件——记得给Filebeat加
adm组 - 日志轮转时采集器还在读旧文件——用
close_inactive参数控制 - 多行日志被拆成多条——比如Java异常栈,用
multiline配置合并 - 采集器把磁盘IO打满——限制
harvester_buffer_size和max_bytes
2.5 知识体系总览
下面这张图,把本章的核心逻辑串起来了。你想想看,日志从产生到最终被分析,经历了哪些环节:
说白了,整个流程就是:日志从应用产生,经过rsyslog或journald收集到本地文件,logrotate负责管理文件大小和数量,然后通过Filebeat或rsyslog转发到远程平台做集中分析。每一步都有坑,每一步也都有优化空间。
/var/log/messages、/var/log/secure 和应用的关键日志采好,跑通整个链路。等稳定了,再逐步加其他日志。一口吃不成胖子,日志系统也是。
好了,这一章的内容就到这儿。日志系统是运维的基石,花时间把它搞扎实了,后面排查问题会轻松很多。
公众号:蓝海资料掘金营,微信deep3321