Linux 日志告警规则设计与实现

5次阅读

告警规则分别写在 rsyslog 的 /etc/rsyslog.d/ 和 syslog-ng 的 /etc/syslog-ng/conf.d/;rsyslog 用 if $msg contains 或 re_match() 匹配,需加 $programname 等上下文过滤;输出链路需检查权限、防火墙和本地落地验证;必须配置 rate-limit 防止洪峰告警。

Linux 日志告警规则设计与实现

告警规则写在哪儿?rsyslogsyslog-ng 路径不同

linux 系统日志告警不是靠“加个插件”就能生效,得先确认你用的是哪个日志守护进程。大多数 centos/RHEL 7+ 默认用 rsyslog,而 debian/ubuntu 22.04+ 开始默认切到 syslog-ng——两者的规则语法、配置位置、加载机制完全不同,混用必失效。

  • rsyslog 规则写在 /etc/rsyslog.d/ 下的 .conf 文件里,比如 /etc/rsyslog.d/99-alert.conf;必须以 $ActionFileDefaultTemplatetemplate 定义输出格式,再用 if $msg contains 'Failed password' then ... 这类条件触发
  • syslog-ng 规则写在 /etc/syslog-ng/conf.d/(或主配置里的 Filter + destination + log 三段式),匹配靠正则:filter f_ssh_fail { message(".*Failed password.*"); };
  • 改完配置后,rsyslogsudo systemctl reload rsyslogsyslog-ng 必须用 sudo syslog-ng-ctl reloadsystemctl reload 在某些版本不生效)

if $msg contains 为什么总漏报?匹配逻辑太粗糙

rsyslogcontains 是纯子串匹配,不支持正则,也不区分大小写(除非显式加 ignorecase),更不会跨行。实际日志里,“authentication failure” 可能出现在第二行,或者被缩写成 auth fail,又或者带时间戳前缀干扰匹配。

  • 优先换 re_match($msg, "Failed password for invalid user|Connection closed by"),它支持 PCRE 正则,且可一次写多个模式
  • 避免只匹配关键词,比如 "Error"——内核日志、cron、journal 都会刷这个,告警爆炸是常态
  • 加上下文过滤:用 $programname == 'sshd'$syslogfacility-text == 'auth' 限定来源,比单靠消息体可靠得多

告警发出去了,但收不到?action 输出链路常断在三处

写好规则只是第一步,真正卡住的地方往往在“怎么送出去”。常见的是本地命令执行失败、网络请求超时、或权限不足导致写入临时文件失败。

  • omprog 调外部脚本时,脚本必须有可执行权限(chmod +x),且第一行 #!/usr/bin/env bash 路径要真实存在;rsyslog 默认以 syslog 用户运行,不能直接 curl 写入需认证的 Webhook
  • omfwd 发 TCP/udp 到告警平台时,务必检查防火墙:sudo ss -tuln | grep :514 看端口是否监听,sudo tcpdump -i lo port 514 确认包发出没
  • 测试阶段别省事:在规则末尾加一行 *.* /var/log/debug_alert.log,把所有匹配日志落地,比盲等邮件/钉钉强十倍

为什么凌晨三点批量告警?rate limit 不设等于自扰

一条 SSH 暴力破解日志每秒刷几十条,没限流规则的话,一分钟能触发上千次告警。不是规则没写对,是压根没防住洪峰。

  • rsyslog$SystemLogRateLimitInterval 60$SystemLogRateLimitBurst 5 控制全局速率(单位:秒 + 条数),但这是针对整个 rsyslog 进程,不够精细
  • 更稳妥的是在规则里嵌套限流:用 call rate_limit 定义模板,再配合 if $msg re_match ... and not (rate_limit()) then ...
  • syslog-ng 原生支持 rate-limit(5) 参数,直接写在 log 块里,比 rsyslog 清晰不少

真正的麻烦不在语法,而在日志格式本身——不同服务输出结构不一,同一服务升级后字段可能变动,靠固定字符串匹配迟早翻车。留个心眼:关键告警规则上线前,先用 journalctl -u sshd -n 100 --no-pager 抽样看原始日志长什么样,别光盯着文档抄示例。

text=ZqhQzanResources