4. 日志体系与集中管理

日志是服务器运维中最基础、也最容易被低估的数据源。它既记录了内核启动、服务启停、认证失败、磁盘告警等关键事件,也是故障复盘时唯一能还原时间线的证据。RHEL 的日志体系由三部分协作构成:rsyslog 负责按设施和优先级把日志分流到不同文件,systemd-journald 负责采集内核与服务的结构化日志,logrotate 负责控制日志文件的体积与生命周期。当服务器数量超过几台之后,还需要把日志远程转发到集中存储,否则每台机器都是一个信息孤岛。

rsyslog 的设施、优先级与规则语法

rsyslog 的核心是“选择器 + 动作”。选择器写成 facility.priority,facility 表示日志来源类别,常见的有 authpriv(认证与 sudo)、kern(内核)、mail、cron、local0~local7(留给自定义应用);priority 从低到高为 debug、info、notice、warning、err、crit、alert、emerg。规则 authpriv.* /var/log/secure 的含义是:所有认证相关日志写入 /var/log/secure。优先级具有“向上包含”特性,写 *.err 会同时匹配 err、crit、alert、emerg,而 *.=err 只匹配 err 本身。

RHEL 9 的配置放在 /etc/rsyslog.conf 与 /etc/rsyslog.d/*.conf。修改后不要直接重启,先用 rsyslogd -N1 做语法检查,确认无报错再 systemctl restart rsyslog。下面是一段可直接参考的自定义规则示例,把本机应用日志按级别拆分:

# /etc/rsyslog.d/10-app.conf
module(load="imuxsock")          # 接收本地 syslog socket
module(load="imjournal" StateFile="imjournal.state")  # 读取 journal

template(name="appFmt" type="string"
         string="%timegenerated% %hostname% %syslogtag%%msg%\n")

if $programname == "myapp" and $syslogseverity <= 4 then {
    action(type="omfile" file="/var/log/myapp-error.log" template="appFmt")
    stop
}
if $programname == "myapp" then {
    action(type="omfile" file="/var/log/myapp.log" template="appFmt")
}

这里 $syslogseverity <= 4 对应 warning 及更严重的级别(数值越小越严重),stop 表示命中后不再继续匹配后续规则,避免同一条日志重复落盘。判断规则是否生效,可用 logger -p local0.err "test-err" 手动注入一条日志,再 tail -f /var/log/myapp-error.log 观察是否出现。

journalctl 持久化与高效查询

journald 默认把日志放在 /run/log/journal,属于内存文件系统,重启即丢。要保留历史,需要创建 /var/log/journal 目录并重启 journald:

mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald
journalctl --disk-usage

持久化之后,查询能力才真正体现价值。journalctl -u sshd -p err --since "2024-06-01" --until "2024-06-02" 可以精确锁定某服务某时间段的错误;journalctl -b -1 查看上一次启动的日志,对排查“重启后服务没起来”非常有用;journalctl _PID=1234 或 journalctl /usr/sbin/sshd 则按进程或可执行文件过滤。日志占用的空间由 /etc/systemd/journald.conf 中的 SystemMaxUse、MaxRetentionSec 控制,例如设为 SystemMaxUse=2G 可防止 journal 无限膨胀。

logrotate 策略与轮转验证

logrotate 通常由 cron 或 systemd timer 每日触发,主配置 /etc/logrotate.conf,应用级策略放在 /etc/logrotate.d/。一个典型策略如下:

/var/log/myapp.log {
    daily
    rotate 14
    size 100M
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root adm
    sharedscripts
    postrotate
        /bin/systemctl reload myapp.service >/dev/null 2>&1 || true
    endscript
}

含义是:每天轮转一次,但文件达到 100M 也提前触发;保留 14 份历史;压缩旧文件但延迟一轮压缩当前文件;文件不存在不报错;空文件不轮转;新文件权限 0640、属主 root:adm;轮转后通知应用重新打开日志句柄。验证时不要等一天,用 logrotate -d /etc/logrotate.d/myapp 做 dry-run 查看决策过程,确认无误后用 logrotate -f 强制执行一次,再 ls -l /var/log/myapp.log* 检查是否生成 .1、.2.gz 等文件。

远程日志转发与集中存储

集中存储的关键是让客户端把日志推送到日志服务器。rsyslog 支持 UDP、TCP 和 RELP 三种传输:UDP 最快但可能丢包,TCP 可靠但需处理断连,RELP 在 TCP 之上增加了应用层确认,适合对完整性要求高的场景。客户端配置:

# /etc/rsyslog.d/50-remote.conf
*.* action(type="omfwd"
           target="10.0.0.20" port="514"
           protocol="tcp"
           action.resumeRetryCount="-1"
           queue.type="linkedList"
           queue.filename="fwdq"
           queue.saveOnShutdown="on")

服务端在 /etc/rsyslog.conf 中启用接收模块,并按来源主机分目录存放,便于后续检索:

module(load="imtcp")
input(type="imtcp" port="514")

template(name="remoteFmt" type="string"
         string="/var/log/remote/%HOSTNAME%/%$YEAR%-%$MONTH%-%$DAY%.log")
*.* action(type="omfile" dynaFile="remoteFmt")

这样每台客户端的日志会落到 /var/log/remote/主机名/日期.log。判断转发是否成功,可在客户端执行 logger -p local0.info "remote-test",然后在服务端对应目录中 grep remote-test。若没有出现,依次检查服务端 514 端口是否监听(ss -lntup | grep 514)、firewalld 是否放行、SELinux 是否允许 rsyslog 写目标目录。

RHEL 日志采集、轮转与集中转发链路 客户端主机 10.0.0.11 内核 / 服务 / 应用 authpriv · kern · local0 systemd-journald /var/log/journal rsyslogd 选择器 facility.priority → 动作 omfile / omfwd /etc/rsyslog.d/*.conf 本地日志文件 /var/log/secure /var/log/myapp.log logrotate daily / rotate 14 compress · postrotate omfwd 转发队列 protocol=tcp · queue.type=linkedList 断连重试 resumeRetryCount=-1 TCP 514 UDP 快但可能丢包 / RELP 带确认 日志服务器 10.0.0.20 rsyslogd 接收端 module(load="imtcp") · input port 514 动态模板 dynaFile /var/log/remote/%HOSTNAME%/ %$YEAR%-%$MONTH%-%$DAY%.log 集中存储目录 remote/web01/2024-06-01.log remote/db01/2024-06-01.log 检索与告警 grep / journalctl / 日志分析平台 验证:logger -p local0.info "remote-test" → 服务端 grep

三者的协作关系与排障要点

把上面三块串起来看:journald 是“采集层”,rsyslog 是“分流与转发层”,logrotate 是“生命周期管理层”。一条日志可能同时存在于 journal 和 /var/log/messages,也可能被转发到远端,因此排障时要先确认“在哪一层丢了”。常见判断路径是:本地 logger 能写入但远端没有,问题在 omfwd 或网络;远端有日志但本地文件不轮转,问题在 logrotate 配置或 cron/timer 未执行;journalctl 查不到历史,多半是 /var/log/journal 未创建或 Storage 仍为 volatile。

远程转发默认使用明文传输,跨公网时应叠加 TLS(gtls 驱动)或走内网专线;同时注意服务端磁盘容量,集中存储很容易被某台主机的 debug 日志迅速占满,建议在服务端也配置 logrotate 与磁盘告警。

最后给出一个可执行的检查清单,用于上线前确认日志链路完整:

检查项命令 / 位置预期结果
rsyslog 语法rsyslogd -N1无 error,退出码 0
journal 持久化ls /var/log/journal存在机器 ID 目录
journal 容量journalctl --disk-usage不超过 SystemMaxUse
logrotate 决策logrotate -d <conf>轮转条件符合预期
远端端口ss -lntup | grep 514服务端处于 LISTEN
端到端验证logger + 服务端 grep测试消息出现在远端文件

掌握这套体系后,日志就不再是散落在各台机器上的文本,而是一条可查询、可轮转、可集中追溯的数据链路,为后续的监控告警和故障复盘提供可靠输入。